diff --git a/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc b/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc new file mode 100644 index 00000000..ebda9951 --- /dev/null +++ b/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc @@ -0,0 +1,111 @@ +--- +description: Use Bun instead of Node.js, npm, pnpm, or vite. +globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json" +alwaysApply: false +--- + +Default to using Bun instead of Node.js. + +- Use `bun ` instead of `node ` or `ts-node ` +- Use `bun test` instead of `jest` or `vitest` +- Use `bun build ` instead of `webpack` or `esbuild` +- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install` +- Use `bun run + + +``` + +With the following `frontend.tsx`: + +```tsx#frontend.tsx +import React from "react"; +import { createRoot } from "react-dom/client"; + +// import .css files directly and it works +import './index.css'; + +const root = createRoot(document.body); + +export default function Frontend() { + return

Hello, world!

; +} + +root.render(); +``` + +Then, run index.ts + +```sh +bun --hot ./index.ts +``` + +For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`. diff --git a/.gitignore b/.gitignore index 7b958523..fe0c3414 100644 --- a/.gitignore +++ b/.gitignore @@ -1,141 +1,142 @@ -# Gitignore for Universal Crypto MCP -################################################################ - -# System files -.DS_Store -Thumbs.db -ehthumbs.db -Desktop.ini - -# Linux/Ubuntu system files -*~ -*.swp -*.swo -.fuse_hidden* -.directory -.Trash-* -.nfs* -.gvfs-fuse-daemon-* - -# IDE and editors -.idea/ -*.sublime-* -.history/ -.windsurfrules -*.code-workspace -.vscode/sessions.json - -# Temporary files -.temp/ -temp/ -tmp/ -*.tmp -*.temp -*.log -*.cache -.cache/ - -# Environment files -.env -.env.local -.env*.local -.env.development -venv/ -.venv/ -.env.example.development -.env.example -.env.desktop -.env* -.env.sentry-build-plugin - -# Dependencies -node_modules/ -*.lock -package-lock.json -bun.lockb -.pnpm-store/ -/.pnp -.pnp.js - -# Build outputs -dist/ -es/ -/lib/ -.next/ -/out/ -/build -logs/ -test-output/ -*.tsbuildinfo -next-env.d.ts - -# Framework specific -# Umi -.umi/ -.umi-production/ -.umi-test/ -.dumi/tmp*/ - -# Vercel -.vercel/ - -# Testing and CI -coverage/ -.coverage/ -.nyc_output/ -.eslintcache -.stylelintcache - -# Database -/prisma/db.sqlite -/prisma/db.sqlite-journal -db.sqlite - -# Debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# Misc -*.pem -src/tools/binance-spot/a.sh -a.sh -src/tools/binance-spot/a.txt - -# Service Worker / Serwist -public/sw* -public/swe-worker* - -# Generated files -public/*.js -public/sitemap.xml -public/sitemap-index.xml -sitemap*.xml -robots.txt - -# Git hooks -.husky/prepare-commit-msg - -# Documents and media -*.patch -*.pdf -*.ppt* -*.doc* -*.xls* - -# Cloud service keys -vertex-ai-key.json - -# AI coding tools -.local/ -.claude/ -.mcp.json -CLAUDE.local.md -.serena/** - -# Misc -./packages/lobe-ui -prd -GEMINI.md -e2e/reports +# Gitignore for Universal Crypto MCP +################################################################ + +# System files +.DS_Store +Thumbs.db +ehthumbs.db +Desktop.ini + +# Linux/Ubuntu system files +*~ +*.swp +*.swo +.fuse_hidden* +.directory +.Trash-* +.nfs* +.gvfs-fuse-daemon-* + +# IDE and editors +.idea/ +*.sublime-* +.history/ +.windsurfrules +*.code-workspace +.vscode/sessions.json + +# Temporary files +.temp/ +temp/ +tmp/ +*.tmp +*.temp +*.log +*.cache +.cache/ + +# Environment files +.env +.env.local +.env*.local +.env.development +venv/ +.venv/ +.env.example.development +.env.example +.env.desktop +.env* +.env.sentry-build-plugin +config.json + +# Dependencies +node_modules/ +*.lock +package-lock.json +bun.lockb +.pnpm-store/ +/.pnp +.pnp.js + +# Build outputs +dist/ +es/ +/lib/ +.next/ +/out/ +/build +logs/ +test-output/ +*.tsbuildinfo +next-env.d.ts + +# Framework specific +# Umi +.umi/ +.umi-production/ +.umi-test/ +.dumi/tmp*/ + +# Vercel +.vercel/ + +# Testing and CI +coverage/ +.coverage/ +.nyc_output/ +.eslintcache +.stylelintcache + +# Database +/prisma/db.sqlite +/prisma/db.sqlite-journal +db.sqlite + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# Misc +*.pem +src/tools/binance-spot/a.sh +a.sh +src/tools/binance-spot/a.txt + +# Service Worker / Serwist +public/sw* +public/swe-worker* + +# Generated files +public/*.js +public/sitemap.xml +public/sitemap-index.xml +sitemap*.xml +robots.txt + +# Git hooks +.husky/prepare-commit-msg + +# Documents and media +*.patch +*.pdf +*.ppt* +*.doc* +*.xls* + +# Cloud service keys +vertex-ai-key.json + +# AI coding tools +.local/ +.claude/ +.mcp.json +CLAUDE.local.md +.serena/** + +# Misc +./packages/lobe-ui +prd +GEMINI.md +e2e/reports diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..672d96f2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..ee9373a9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "eslint.useFlatConfig": true +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..19286676 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# syntax=docker/dockerfile:1 +# oven/bun:1 tracks latest Bun 1.x (includes 1.2+ text lockfile default). No lockfile COPY: +# .gitignore uses *.lock and lockfiles are often absent in clones — install resolves from package.json. + +FROM oven/bun:1 AS builder +WORKDIR /app + +COPY package.json ./ +RUN bun install + +COPY tsconfig.json ./ +COPY src ./src +RUN bun run build + +FROM oven/bun:1-slim AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV PORT=3002 + +COPY package.json ./ +RUN bun install --production + +COPY --from=builder /app/build ./build + +EXPOSE 3002 + +# Streamable HTTP (SSE-compatible endpoints: /mcp, /sse, health: /health) +CMD ["bun", "run", "build/index.js", "--sse"] + +HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ + CMD bun -e "fetch('http://127.0.0.1:'+(process.env.PORT||'3002')+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" diff --git a/README.md b/README.md index a3c67cdf..45c637bd 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,29 @@ npm run dev # STDIO npm run dev:sse # SSE ``` +### Troubleshooting: "Invalid API-key, IP, or permissions" + +If you use **IP whitelist** on Binance and see this error, Binance may be seeing a different IP than the one you whitelisted: + +- **Proxy** — The process can inherit `HTTP_PROXY` / `HTTPS_PROXY` (e.g. from Cursor or your shell). Outbound requests to Binance then go through the proxy, so Binance sees the proxy’s IP. +- **VPN** — System-wide VPN changes your exit IP. +- **IPv4 vs IPv6** — Your machine might reach Binance via IPv6 while you whitelisted an IPv4 address (or the reverse). + +**Fix (proxy):** Bypass the proxy for Binance by setting `NO_PROXY` when starting the server. In `.env`: + +```env +NO_PROXY=api.binance.com,api1.binance.com,api2.binance.com,api3.binance.com +``` + +Or in the shell before running: + +```bash +export NO_PROXY=api.binance.com,api1.binance.com,api2.binance.com,api3.binance.com +npm run dev:sse +``` + +If using Cursor’s MCP config, add `NO_PROXY` to the server’s `env` so the MCP process gets it. + --- ## 🖥️ Client Configuration diff --git a/config.json b/config.json deleted file mode 100644 index f769e982..00000000 --- a/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "mcpServers": { - "binance-mcp": { - "command": "node", - "args": [ - "/Users/Username/Desktop/bsc-mpc/build/index.js" - ], - "env": { - "BINANCE_API_KEY": "BINANCE_API_KEY", - "BINANCE_API_SECRET": "BINANCE_API_SECRET" - }, - "disabled": false, - "autoApprove": [] - } - } -} - diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..cac0b5e9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + binance-mcp: + build: + context: . + dockerfile: Dockerfile + image: binance-mcp:latest + container_name: binance-mcp + restart: unless-stopped + # App listens on 3002 inside the container; host port 80 is the default (override with HOST_PORT). + ports: + - "${HOST_PORT:-80}:3002" + env_file: + - .env + environment: + PORT: "3002" diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..fd991e9a --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,56 @@ +import js from "@eslint/js" +import stylistic from "@stylistic/eslint-plugin" +import perfectionist from "eslint-plugin-perfectionist" +import tseslint from "typescript-eslint" +import prettierConfig from "eslint-config-prettier" + +export default tseslint.config( + js.configs.recommended, + ...tseslint.configs.strict, + ...tseslint.configs.stylistic, + prettierConfig, + { + plugins: { + "@stylistic": stylistic, + perfectionist, + }, + rules: { + "@stylistic/padding-line-between-statements": [ + "error", + { blankLine: "always", prev: "*", next: "return" }, + ], + "perfectionist/sort-imports": [ + "error", + { + type: "natural", + order: "asc", + groups: [ + "type", + "builtin", + "external", + "internal", + "parent", + "sibling", + "index", + "side-effect", + ], + newlinesBetween: 1, + }, + ], + "perfectionist/sort-named-imports": ["error", { type: "natural", order: "asc" }], + "@typescript-eslint/consistent-type-imports": [ + "error", + { prefer: "type-imports", fixStyle: "separate-type-imports" }, + ], + "@stylistic/semi": ["error", "always"], + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, + ], + }, + }, + { + ignores: ["build/**", "node_modules/**"], + }, +) diff --git a/package.json b/package.json index 1112aafd..f4bb6155 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,18 @@ "type": "module", "main": "./build/index.js", "scripts": { - "start": "node build/index.js", - "start:sse": "node build/index.js --sse", - "dev": "tsx watch src/index.ts", - "dev:sse": "tsx watch src/index.ts --sse", + "start": "bun run build/index.js", + "start:sse": "bun run build/index.js --sse", + "dev": "bun --watch src/index.ts", + "dev:sse": "bun --watch src/index.ts --sse", "build": "tsc", - "init": "tsx src/init.ts", - "test": "npx @modelcontextprotocol/inspector tsx src/index.ts" + "init": "bun src/init.ts", + "test": "bunx @modelcontextprotocol/inspector bun src/index.ts --sse", + "test:stdio": "bunx @modelcontextprotocol/inspector bun src/index.ts", + "lint": "eslint src/", + "lint:fix": "eslint src/ --fix", + "format": "prettier --write \"src/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\"" }, "bin": { "binance-mcp": "./build/index.js" @@ -63,27 +68,33 @@ "@binance/vip-loan": "^8.0.0", "@binance/wallet": "^15.0.0", "@modelcontextprotocol/sdk": "^1.11.0", - "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.18.2", "zod": "^3.22.4" }, "devDependencies": { - "@types/cors": "^2.8.17", + "@eslint/js": "^10.0.1", + "@stylistic/eslint-plugin": "^5.10.0", + "@types/bun": "latest", "@types/express": "^4.17.21", + "@types/figlet": "^1.5.8", + "@types/fs-extra": "^11.0.4", "@types/node": "^20.0.0", + "@types/prompts": "^2.4.9", "chalk": "^5.3.0", + "eslint": "^10.0.3", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-perfectionist": "^5.6.0", "figlet": "^1.8.0", "fs-extra": "^11.2.0", + "prettier": "^3.8.1", "prompts": "^2.4.2", - "@types/figlet": "^1.5.8", - "@types/fs-extra": "^11.0.4", - "@types/prompts": "^2.4.9", - "tsx": "^4.7.0", - "typescript": "^5.0.0" + "typescript": "^5.0.0", + "typescript-eslint": "^8.57.0" }, "license": "MIT", "engines": { - "node": ">=18.0.0" - } + "bun": ">=1.3.9" + }, + "private": true } diff --git a/scripts/codemod-register-tool-5-to-3.mjs b/scripts/codemod-register-tool-5-to-3.mjs new file mode 100644 index 00000000..4228d575 --- /dev/null +++ b/scripts/codemod-register-tool-5-to-3.mjs @@ -0,0 +1,207 @@ +#!/usr/bin/env node +/** + * Codemod: Convert 5-arg server.registerTool(name, {}, description, inputSchema, cb) + * to 3-arg server.registerTool(name, { description, inputSchema }, cb) + * and add explicit param types to avoid implicit any. + */ +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const SRC = path.join(__dirname, "..", "src"); + +const FILES = [ + path.join(SRC, "tools/custodial/index.ts"), + path.join(SRC, "tools/custodial-solution/index.ts"), + path.join(SRC, "tools/creditline/index.ts"), +]; + +function findMatchingBrace(str, start, open = "{", close = "}") { + let depth = 0; + for (let i = start; i < str.length; i++) { + if (str[i] === open) depth++; + else if (str[i] === close) { + depth--; + if (depth === 0) return i; + } + } + return -1; +} + +function findMatchingParen(str, start) { + return findMatchingBrace(str, start, "(", ")"); +} + +function findTemplateLiteralEnd(str, start) { + let i = start; + if (str[i] !== "`") return -1; + i++; + while (i < str.length) { + if (str[i] === "\\") { + i += 2; + continue; + } + if (str[i] === "`") return i; + if (str[i] === "${") { + const end = findMatchingBrace(str, i + 1, "{", "}"); + if (end >= 0) i = end + 1; + else i++; + continue; + } + i++; + } + return -1; +} + +function transformFile(filePath) { + let content = fs.readFileSync(filePath, "utf8"); + const original = content; + let changed = false; + + while (true) { + const idx = content.indexOf("server.registerTool("); + if (idx < 0) break; + const openParen = idx + "server.registerTool".length; + const closeParen = findMatchingParen(content, openParen); + if (closeParen < 0) break; + + const argsStr = content.slice(openParen + 1, closeParen); + let i = 0; + while (i < argsStr.length && /\s/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + + const firstCh = argsStr[i]; + if (firstCh !== '"' && firstCh !== "'") break; + const q = firstCh; + let nameEnd = i + 1; + while (nameEnd < argsStr.length && argsStr[nameEnd] !== q) { + if (argsStr[nameEnd] === "\\") nameEnd++; + nameEnd++; + } + const name = argsStr.slice(i + 1, nameEnd).replace(/\\"/g, '"'); + i = nameEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + if (argsStr[i] !== "{") break; + const emptyEnd = findMatchingBrace(argsStr, i); + if (emptyEnd < 0) break; + const emptyStr = argsStr.slice(i, emptyEnd + 1); + if (emptyStr.replace(/\s/g, "") !== "{}") break; + i = emptyEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + if (argsStr[i] !== "`") break; + const descEnd = findTemplateLiteralEnd(argsStr, i); + if (descEnd < 0) break; + const description = argsStr.slice(i, descEnd + 1); + i = descEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length || argsStr[i] !== "{") break; + const schemaEnd = findMatchingBrace(argsStr, i); + if (schemaEnd < 0) break; + const schemaStr = argsStr.slice(i, schemaEnd + 1); + i = schemaEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + const callbackStr = argsStr.slice(i).trim(); + if (!callbackStr.startsWith("async")) break; + + const configObj = `{\n description: ${description},\n inputSchema: ${schemaStr},\n }`; + let newCallback = callbackStr; + const paramsMatch = callbackStr.match(/async\s*\(\s*\{\s*([^}]*)\s*\}\s*\)\s*=>/); + if (paramsMatch) { + const keys = paramsMatch[1].split(",").map((k) => k.trim()); + const typeStr = keys.map((k) => `${k}?: unknown`).join("; "); + newCallback = callbackStr.replace( + /async\s*\(\s*\{\s*[^}]*\s*\}\s*\)\s*=>/, + `async (params: { ${typeStr} }) => { const { ${keys.join(", ")} } = params;` + ); + } else if (callbackStr.includes("async (params)")) { + newCallback = callbackStr.replace("async (params)", "async (params: Record)"); + } + + const newArgs = `"${name.replace(/"/g, '\\"')}",\n ${configObj},\n ${newCallback}`; + content = + content.slice(0, idx) + + "server.registerTool(" + + newArgs + + content.slice(closeParen); + changed = true; + } + + if (changed) { + fs.writeFileSync(filePath, content, "utf8"); + return true; + } + return false; +} + +for (const filePath of FILES) { + if (!fs.existsSync(filePath)) { + console.warn("Skip (not found):", filePath); + continue; + } + let count = 0; + while (true) { + const content = fs.readFileSync(filePath, "utf8"); + const idx = content.indexOf("server.registerTool("); + if (idx < 0) break; + const openParen = content.indexOf("(", idx); + const closeParen = findMatchingParen(content, openParen); + if (closeParen < 0) break; + const argsStr = content.slice(openParen + 1, closeParen); + let i = 0; + while (i < argsStr.length && /\s/.test(argsStr[i])) i++; + if (i >= argsStr.length || (argsStr[i] !== '"' && argsStr[i] !== "'")) break; + const q = argsStr[i]; + const nameStart = i + 1; + let nameEnd = nameStart; + while (nameEnd < argsStr.length && argsStr[nameEnd] !== q) { + if (argsStr[nameEnd] === "\\") nameEnd++; + nameEnd++; + } + const name = argsStr.slice(nameStart, nameEnd).replace(/\\"/g, '"'); + i = nameEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length || argsStr[i] !== "{") break; + const emptyEnd = findMatchingBrace(argsStr, i); + if (emptyEnd < 0 || argsStr.slice(i, emptyEnd + 1).replace(/\s/g, "") !== "{}") break; + i = emptyEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length || argsStr[i] !== "`") break; + const descEnd = findTemplateLiteralEnd(argsStr, i); + if (descEnd < 0) break; + const description = argsStr.slice(i, descEnd + 1); + i = descEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length || argsStr[i] !== "{") break; + const schemaEnd = findMatchingBrace(argsStr, i); + if (schemaEnd < 0) break; + const schemaStr = argsStr.slice(i, schemaEnd + 1); + i = schemaEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + const callbackStr = argsStr.slice(i).trim(); + if (!callbackStr.startsWith("async")) break; + const configObj = `{\n description: ${description},\n inputSchema: ${schemaStr},\n }`; + let newCallback = callbackStr; + const paramsMatch = callbackStr.match(/async\s*\(\s*\{\s*([^}]*)\s*\}\s*\)\s*=>/); + if (paramsMatch) { + const keys = paramsMatch[1].split(",").map((k) => k.trim()); + const typeStr = keys.map((k) => `${k}?: unknown`).join("; "); + newCallback = callbackStr.replace( + /async\s*\(\s*\{\s*[^}]*\s*\}\s*\)\s*=>/, + `async (params: { ${typeStr} }) => { const { ${keys.join(", ")} } = params;` + ); + } else if (callbackStr.includes("async (params)")) { + newCallback = callbackStr.replace("async (params)", "async (params: Record)"); + } + const newArgs = `"${name.replace(/"/g, '\\"')}",\n ${configObj},\n ${newCallback}`; + const newContent = + content.slice(0, idx) + "server.registerTool(" + newArgs + content.slice(closeParen + 1); + fs.writeFileSync(filePath, newContent, "utf8"); + count++; + } + if (count > 0) console.log("Updated", count, "tool(s) in", path.relative(SRC, filePath)); +} + +console.log("Done."); diff --git a/scripts/codemod-register-tool.mjs b/scripts/codemod-register-tool.mjs new file mode 100644 index 00000000..0066def3 --- /dev/null +++ b/scripts/codemod-register-tool.mjs @@ -0,0 +1,183 @@ +#!/usr/bin/env node +/** + * Codemod: Replace deprecated server.tool(...) with server.registerTool(...). + * Patterns: + * server.tool(name, description, schema, cb) -> server.registerTool(name, { description, inputSchema: schema }, cb) + * server.tool(name, description, {}, cb) -> server.registerTool(name, { description }, cb) + * server.tool(name, schema, cb) -> server.registerTool(name, { inputSchema: schema }, cb) + */ +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const SRC = path.join(__dirname, "..", "src"); + +function findMatchingBrace(str, start, open = "{", close = "}") { + let depth = 0; + for (let i = start; i < str.length; i++) { + if (str[i] === open) depth++; + else if (str[i] === close) { + depth--; + if (depth === 0) return i; + } + } + + return -1; +} + +function findMatchingParen(str, start) { + return findMatchingBrace(str, start, "(", ")"); +} + +/** Find end of next top-level argument (string, object, or async function start). */ +function skipArg(content, i) { + const rest = content.slice(i); + const trimmed = rest.replace(/^\s*,?\s*/s, ""); + const skipped = rest.length - trimmed.length; + i += skipped; + const ch = content[i]; + if (ch === '"' || ch === "'") { + const q = ch; + i++; + while (i < content.length && content[i] !== q) { + if (content[i] === "\\") i++; + i++; + } + + return i + 1; + } + if (ch === "{") { + const end = findMatchingBrace(content, i); + + return end >= 0 ? end + 1 : i; + } + if (ch === "(") { + const end = findMatchingParen(content, i); + + return end >= 0 ? end + 1 : i; + } + if (ch === "a" && content.slice(i, i + 5) === "async") { + const parenStart = content.indexOf("(", i); + if (parenStart >= 0) { + const end = findMatchingParen(content, parenStart); + + return end >= 0 ? end + 1 : i; + } + } + + return i; +} + +function transformFile(filePath) { + let content = fs.readFileSync(filePath, "utf8"); + const original = content; + let changed = false; + + while (true) { + const idx = content.indexOf("server.tool("); + if (idx < 0) break; + + const openParen = idx + "server.tool".length; + const closeParen = findMatchingParen(content, openParen); + if (closeParen < 0) break; + + const argsStr = content.slice(openParen + 1, closeParen); + let i = 0; + while (i < argsStr.length && /\s/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + + const firstCh = argsStr[i]; + if (firstCh !== '"' && firstCh !== "'") break; + + const q = firstCh; + let nameEnd = i + 1; + while (nameEnd < argsStr.length && argsStr[nameEnd] !== q) { + if (argsStr[nameEnd] === "\\") nameEnd++; + nameEnd++; + } + const name = argsStr.slice(i + 1, nameEnd).replace(/\\"/g, '"'); + i = nameEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + const secondCh = argsStr[i]; + let description = null; + let schemaStr = null; + + if (secondCh === '"' || secondCh === "'") { + const q2 = secondCh; + let descEnd = i + 1; + while (descEnd < argsStr.length && argsStr[descEnd] !== q2) { + if (argsStr[descEnd] === "\\") descEnd++; + descEnd++; + } + description = argsStr.slice(i + 1, descEnd).replace(/\\"/g, '"'); + i = descEnd + 1; + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + if (i >= argsStr.length) break; + if (argsStr[i] === "{") { + const end = findMatchingBrace(argsStr, i); + schemaStr = end >= 0 ? argsStr.slice(i, end + 1) : "{}"; + i = end + 1; + } + } else if (secondCh === "{") { + const end = findMatchingBrace(argsStr, i); + schemaStr = end >= 0 ? argsStr.slice(i, end + 1) : "{}"; + i = end + 1; + } + + while (i < argsStr.length && /[\s,]/.test(argsStr[i])) i++; + const callbackStart = i; + const callbackStr = argsStr.slice(callbackStart).trim(); + const restOfCall = content.slice(closeParen + 1); + + const isEmptySchema = + schemaStr === "{}" || (schemaStr && schemaStr.replace(/\s/g, "") === "{}"); + let configObj; + if (description !== null && isEmptySchema) { + configObj = `{ description: ${JSON.stringify(description)} }`; + } else if (description !== null && schemaStr) { + configObj = `{\n description: ${JSON.stringify(description)},\n inputSchema: ${schemaStr},\n }`; + } else if (schemaStr) { + configObj = `{\n inputSchema: ${schemaStr},\n }`; + } else { + configObj = "{}"; + } + + const newArgs = `"${name.replace(/"/g, '\\"')}",\n ${configObj},\n ${callbackStr}`; + content = content.slice(0, idx) + "server.registerTool(" + newArgs + content.slice(closeParen); + changed = true; + } + + if (changed) { + fs.writeFileSync(filePath, content, "utf8"); + + return true; + } + + return false; +} + +function walk(dir) { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + for (const e of entries) { + const full = path.join(dir, e.name); + if (e.isDirectory() && e.name !== "node_modules") { + walk(full); + } else if (e.isFile() && e.name.endsWith(".ts")) { + try { + const raw = fs.readFileSync(full, "utf8"); + if (raw.includes("server.tool(")) { + if (transformFile(full)) { + console.log("Updated:", path.relative(SRC, full)); + } + } + } catch (err) { + console.error("Error processing", full, err.message); + } + } + } +} + +walk(SRC); +console.log("Done."); diff --git a/src/binance.ts b/src/binance.ts index 3a351158..a68d1bf8 100644 --- a/src/binance.ts +++ b/src/binance.ts @@ -1,27 +1,27 @@ // src/binance.ts // Central registration file for all Binance modules -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { registerBinanceAlgoTools } from "./modules/algo/index.js"; +import { registerBinanceC2CTradeHistoryTools } from "./modules/c2c/index.js"; +import { registerBinanceConvertTools } from "./modules/convert/index.js"; +import { registerBinanceCopyTradingTools } from "./modules/copy-trading/index.js"; +import { registerBinanceDualInvestmentTools } from "./modules/dual-investment/index.js"; +import { registerBinanceFiatDepositWithdrawHistoryTools } from "./modules/fiat/index.js"; +import { registerGiftCard } from "./modules/gift-card/index.js"; +import { registerBinanceMiningTools } from "./modules/mining/index.js"; +import { registerBinanceNFTTools } from "./modules/nft/index.js"; +import { registerBinancePayTools } from "./modules/pay/index.js"; +import { registerPortfolioMargin } from "./modules/portfolio-margin/index.js"; +import { registerBinanceRebateTools } from "./modules/rebate/index.js"; +import { registerBinanceSimpleEarnTools } from "./modules/simple-earn/index.js"; // Import module registration functions -import { registerBinanceSpotTools } from "./modules/spot/index.js" -import { registerBinanceAlgoTools } from "./modules/algo/index.js" -import { registerBinanceSimpleEarnTools } from "./modules/simple-earn/index.js" -import { registerBinanceC2CTradeHistoryTools } from "./modules/c2c/index.js" -import { registerBinanceConvertTools } from "./modules/convert/index.js" -import { registerBinanceWalletTools } from "./modules/wallet/index.js" -import { registerBinanceCopyTradingTools } from "./modules/copy-trading/index.js" -import { registerBinanceFiatDepositWithdrawHistoryTools } from "./modules/fiat/index.js" -import { registerBinanceNFTTools } from "./modules/nft/index.js" -import { registerBinancePayTools } from "./modules/pay/index.js" -import { registerBinanceRebateTools } from "./modules/rebate/index.js" -import { registerBinanceDualInvestmentTools } from "./modules/dual-investment/index.js" -import { registerBinanceMiningTools } from "./modules/mining/index.js" -import { registerBinanceVipLoanTools } from "./modules/vip-loan/index.js" -import { registerBinanceStakingTools } from "./modules/staking/index.js" -import { registerPortfolioMargin } from "./modules/portfolio-margin/index.js" -import { registerGiftCard } from "./modules/gift-card/index.js" -import { registerSubAccount } from "./modules/sub-account/index.js" +import { registerBinanceSpotTools } from "./modules/spot/index.js"; +import { registerBinanceStakingTools } from "./modules/staking/index.js"; +import { registerSubAccount } from "./modules/sub-account/index.js"; +import { registerBinanceVipLoanTools } from "./modules/vip-loan/index.js"; +import { registerBinanceWalletTools } from "./modules/wallet/index.js"; // NOTE: The following modules are disabled due to missing/incompatible npm packages: // - Margin (@binance/margin doesn't exist, needs refactoring to use connector-typescript) @@ -36,37 +36,36 @@ import { registerSubAccount } from "./modules/sub-account/index.js" */ export function registerBinance(server: McpServer) { // Core trading modules - registerBinanceSpotTools(server) - registerBinanceAlgoTools(server) - + registerBinanceSpotTools(server); + registerBinanceAlgoTools(server); + // Earn & Investment modules - registerBinanceSimpleEarnTools(server) - registerBinanceDualInvestmentTools(server) - registerBinanceStakingTools(server) - + registerBinanceSimpleEarnTools(server); + registerBinanceDualInvestmentTools(server); + registerBinanceStakingTools(server); + // Trading modules - registerBinanceC2CTradeHistoryTools(server) - registerBinanceConvertTools(server) - registerBinanceCopyTradingTools(server) - + registerBinanceC2CTradeHistoryTools(server); + registerBinanceConvertTools(server); + registerBinanceCopyTradingTools(server); + // Wallet & Finance modules - registerBinanceWalletTools(server) - registerBinanceFiatDepositWithdrawHistoryTools(server) - registerBinanceVipLoanTools(server) - + registerBinanceWalletTools(server); + registerBinanceFiatDepositWithdrawHistoryTools(server); + registerBinanceVipLoanTools(server); + // Portfolio Margin module - registerPortfolioMargin(server) - + registerPortfolioMargin(server); + // Gift Card module - registerGiftCard(server) - + registerGiftCard(server); + // Sub-Account Management module - registerSubAccount(server) - + registerSubAccount(server); + // Other modules - registerBinanceNFTTools(server) - registerBinancePayTools(server) - registerBinanceRebateTools(server) - registerBinanceMiningTools(server) + registerBinanceNFTTools(server); + registerBinancePayTools(server); + registerBinanceRebateTools(server); + registerBinanceMiningTools(server); } - diff --git a/src/config/binanceClient.ts b/src/config/binanceClient.ts index f74b5b06..28448aeb 100644 --- a/src/config/binanceClient.ts +++ b/src/config/binanceClient.ts @@ -1,34 +1,38 @@ -// src/config/binanceClient.ts -// Existing SDK packages -import { Spot } from "@binance/spot"; -import { Spot as ConnectorSpot } from "@binance/connector-typescript"; -import { SimpleEarn } from "@binance/simple-earn"; +import crypto from "crypto"; + import { Algo } from "@binance/algo"; +import { AutoInvest } from "@binance/auto-invest"; import { C2C } from "@binance/c2c"; +import { Spot as ConnectorSpot } from "@binance/connector-typescript"; import { Convert } from "@binance/convert"; -import { Wallet } from "@binance/wallet"; import { CopyTrading } from "@binance/copy-trading"; +import { CryptoLoan } from "@binance/crypto-loan"; +import { DualInvestment } from "@binance/dual-investment"; import { Fiat } from "@binance/fiat"; +import { Mining } from "@binance/mining"; import { NFT } from "@binance/nft"; import { Pay } from "@binance/pay"; import { Rebate } from "@binance/rebate"; -import { DualInvestment } from "@binance/dual-investment"; -import { Mining } from "@binance/mining"; -import { VIPLoan } from "@binance/vip-loan"; +import { SimpleEarn } from "@binance/simple-earn"; +// src/config/binanceClient.ts +import { Spot } from "@binance/spot"; import { Staking } from "@binance/staking"; -import { AutoInvest } from "@binance/auto-invest"; -import { CryptoLoan } from "@binance/crypto-loan"; import { SubAccount } from "@binance/sub-account"; -import crypto from "crypto"; +import { VIPLoan } from "@binance/vip-loan"; +import { Wallet } from "@binance/wallet"; + +import { assertNotTestnet, IS_TESTNET, URLS } from "./testnet.js"; + +export { assertNotTestnet, IS_TESTNET }; const API_KEY = process.env.BINANCE_API_KEY ?? ""; const API_SECRET = process.env.BINANCE_API_SECRET ?? ""; -const BASE_URL = "https://api.binance.com"; +const BASE_URL = URLS.SPOT_BASE_URL; const configurationRestAPI = { - apiKey: API_KEY, - apiSecret: API_SECRET, - basePath: BASE_URL + apiKey: API_KEY, + apiSecret: API_SECRET, + basePath: BASE_URL, }; // Spot Trading @@ -71,410 +75,844 @@ export const miningClient = new Mining({ configurationRestAPI }); // Generic REST client for APIs without dedicated packages // (Margin, Futures, Options, Gift Card, Portfolio Margin) function generateSignature(queryString: string): string { - return crypto.createHmac("sha256", API_SECRET).update(queryString).digest("hex"); + return crypto.createHmac("sha256", API_SECRET).update(queryString).digest("hex"); } async function makeSignedRequest( - method: "GET" | "POST" | "DELETE", - endpoint: string, - params: Record = {} + method: "GET" | "POST" | "DELETE", + endpoint: string, + params: Record = {}, ): Promise { - const timestamp = Date.now(); - const queryParams = { ...params, timestamp }; - const queryString = new URLSearchParams( - Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [k, String(v)])) - ).toString(); - const signature = generateSignature(queryString); - const url = `${BASE_URL}${endpoint}?${queryString}&signature=${signature}`; - - const response = await fetch(url, { - method, - headers: { - "X-MBX-APIKEY": API_KEY, - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); - } - - return response.json(); + if (IS_TESTNET && endpoint.startsWith("/sapi")) { + throw new Error( + `[Testnet] Endpoint ${endpoint} is not available on the Binance Spot Test Network. ` + + `Only /api endpoints are supported.`, + ); + } + + const timestamp = Date.now(); + const queryParams = { ...params, timestamp }; + const queryString = new URLSearchParams( + Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [k, String(v)])), + ).toString(); + const signature = generateSignature(queryString); + const url = `${BASE_URL}${endpoint}?${queryString}&signature=${signature}`; + + const response = await fetch(url, { + method, + headers: { + "X-MBX-APIKEY": API_KEY, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); + } + + return response.json(); } async function makePublicRequest(endpoint: string, params: Record = {}): Promise { - const queryString = new URLSearchParams( - Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])) - ).toString(); - const url = `${BASE_URL}${endpoint}${queryString ? "?" + queryString : ""}`; - - const response = await fetch(url, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); - } - - return response.json(); + if (IS_TESTNET && endpoint.startsWith("/sapi")) { + throw new Error( + `[Testnet] Endpoint ${endpoint} is not available on the Binance Spot Test Network. ` + + `Only /api endpoints are supported.`, + ); + } + + const queryString = new URLSearchParams( + Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])), + ).toString(); + const url = `${BASE_URL}${endpoint}${queryString ? "?" + queryString : ""}`; + + const response = await fetch(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); + } + + return response.json(); +} + +// Portfolio Margin uses papi.binance.com for trade/account sub-endpoints +const PAPI_BASE_URL = URLS.PAPI_BASE_URL; + +async function makePapiSignedRequest( + method: "GET" | "POST" | "DELETE" | "PUT", + endpoint: string, + params: Record = {}, +): Promise { + const timestamp = Date.now(); + const queryParams = { ...params, timestamp }; + const queryString = new URLSearchParams( + Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [k, String(v)])), + ).toString(); + const signature = generateSignature(queryString); + const url = `${PAPI_BASE_URL}${endpoint}?${queryString}&signature=${signature}`; + + const response = await fetch(url, { + method, + headers: { + "X-MBX-APIKEY": API_KEY, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); + } + + return response.json(); +} + +function wrapData(p: Promise): Promise<{ data: () => Promise }> { + return p.then((data) => ({ data: () => Promise.resolve(data) })); } -// Portfolio Margin client wrapper +// Portfolio Margin client wrapper (includes restAPI for modules that expect .restAPI.method().then(r => r.data())) export const portfolioMarginClient = { - getAccount: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/account", params), - getCollateralRate: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/collateralRate", params), - getBankruptcyLoanAmount: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/pmLoan", params), - repayBankruptcyLoan: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/repay", params), - getInterestHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/interest-history", params), - getAssetIndexPrice: (params: Record = {}) => - makePublicRequest("/sapi/v1/portfolio/asset-index-price", params), - fundAutoCollection: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/auto-collection", params), - fundCollection: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/asset-collection", params), - bnbTransfer: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/bnb-transfer", params), - changeAutoRepayFutures: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/repay-futures-switch", params), - getAutoRepayFuturesStatus: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/repay-futures-switch", params), - repayFuturesNegativeBalance: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/portfolio/repay-futures-negative-balance", params), - getAssetLeverage: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/margin-asset-leverage", params), - getBalance: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/portfolio/balance", params) + getAccount: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/account", params), + getCollateralRate: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/collateralRate", params), + getBankruptcyLoanAmount: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/pmLoan", params), + repayBankruptcyLoan: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/repay", params), + getInterestHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/interest-history", params), + getAssetIndexPrice: (params: Record = {}) => + makePublicRequest("/sapi/v1/portfolio/asset-index-price", params), + fundAutoCollection: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/auto-collection", params), + fundCollection: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/asset-collection", params), + bnbTransfer: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/bnb-transfer", params), + changeAutoRepayFutures: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/repay-futures-switch", params), + getAutoRepayFuturesStatus: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/repay-futures-switch", params), + repayFuturesNegativeBalance: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/portfolio/repay-futures-negative-balance", params), + getAssetLeverage: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/margin-asset-leverage", params), + getBalance: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/portfolio/balance", params), + restAPI: { + account: (params: Record = {}) => + wrapData(makeSignedRequest("GET", "/sapi/v1/portfolio/account", params)), + balance: (params: Record = {}) => + wrapData(makeSignedRequest("GET", "/sapi/v1/portfolio/balance", params)), + umAccount: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/account", params)), + umPositionRisk: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/positionRisk", params)), + cmAccount: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/account", params)), + cmPositionRisk: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/positionRisk", params)), + marginAccount: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/marginAccount", params)), + marginMaxWithdraw: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/marginMaxWithdraw", params)), + marginMaxBorrowable: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/marginMaxBorrowable", params)), + umNewOrder: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/um/order", params)), + umCancelOrder: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/um/order", params)), + umOrder: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/order", params)), + umOpenOrders: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/openOrders", params)), + umAllOrders: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/allOrders", params)), + umUserTrades: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/um/userTrades", params)), + umLeverage: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/um/leverage", params)), + umMarginType: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/um/marginType", params)), + umCancelAllOpenOrders: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/um/allOpenOrders", params)), + cmNewOrder: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/cm/order", params)), + cmCancelOrder: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/cm/order", params)), + cmOrder: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/order", params)), + cmOpenOrders: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/openOrders", params)), + cmAllOrders: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/allOrders", params)), + cmUserTrades: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/cm/userTrades", params)), + cmLeverage: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/cm/leverage", params)), + cmMarginType: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/cm/marginType", params)), + cmCancelAllOpenOrders: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/cm/allOpenOrders", params)), + marginNewOrder: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/margin/order", params)), + marginCancelOrder: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/margin/order", params)), + marginOrder: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/margin/order", params)), + marginOpenOrders: (params: Record = {}) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/margin/openOrders", params)), + marginAllOrders: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/margin/allOrders", params)), + marginMyTrades: (params: Record) => + wrapData(makePapiSignedRequest("GET", "/papi/v1/margin/myTrades", params)), + marginLoan: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/margin/loan", params)), + marginRepay: (params: Record) => + wrapData(makePapiSignedRequest("POST", "/papi/v1/margin/repay", params)), + marginCancelAllOpenOrders: (params: Record) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/margin/allOpenOrders", params)), + createListenKey: () => wrapData(makePapiSignedRequest("POST", "/papi/v1/listenKey", {})), + deleteListenKey: (params: Record = {}) => + wrapData(makePapiSignedRequest("DELETE", "/papi/v1/listenKey", params)), + renewListenKey: (params: Record = {}) => + wrapData(makePapiSignedRequest("PUT", "/papi/v1/listenKey", params)), + }, }; // Gift Card client wrapper export const giftCardClient = { - createCode: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/giftcard/createCode", params), - createDualTokenCode: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/giftcard/buyCode", params), - redeemCode: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/giftcard/redeemCode", params), - verify: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/giftcard/verify", params), - rsaPublicKey: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/giftcard/cryptography/rsa-public-key", params), - buyCode: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/giftcard/buyCode", params), - getTokenLimit: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/giftcard/buyCode/token-limit", params) + createCode: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/giftcard/createCode", params), + createDualTokenCode: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/giftcard/buyCode", params), + redeemCode: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/giftcard/redeemCode", params), + verify: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/giftcard/verify", params), + rsaPublicKey: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/giftcard/cryptography/rsa-public-key", params), + buyCode: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/giftcard/buyCode", params), + getTokenLimit: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/giftcard/buyCode/token-limit", params), + restAPI: { + createCode: (p: Record = {}) => wrapData(giftCardClient.createCode(p)), + createDualTokenCode: (p: Record = {}) => + wrapData(giftCardClient.createDualTokenCode(p)), + redeemCode: (p: Record = {}) => wrapData(giftCardClient.redeemCode(p)), + redeemDualTokenCode: (p: Record = {}) => wrapData(giftCardClient.redeemCode(p)), + verify: (p: Record = {}) => wrapData(giftCardClient.verify(p)), + tokenLimit: (p: Record = {}) => wrapData(giftCardClient.getTokenLimit(p)), + }, }; // Margin client wrapper export const marginClient = { - borrow: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/loan", params), - repay: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/repay", params), - getAccount: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/account", params), - getMaxBorrowable: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/maxBorrowable", params), - getMaxTransferable: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/maxTransferable", params), - transfer: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/transfer", params), - getAllPairs: (params: Record = {}) => - makePublicRequest("/sapi/v1/margin/allPairs", params), - getPriceIndex: (params: Record = {}) => - makePublicRequest("/sapi/v1/margin/priceIndex", params), - newOrder: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/order", params), - cancelOrder: (params: Record = {}) => - makeSignedRequest("DELETE", "/sapi/v1/margin/order", params), - getOpenOrders: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/openOrders", params), - getAllOrders: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/allOrders", params), - getMyTrades: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/myTrades", params), - cancelAllOpenOrders: (params: Record = {}) => - makeSignedRequest("DELETE", "/sapi/v1/margin/openOrders", params), - getLoanRecord: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/loan", params), - getRepayRecord: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/repay", params), - getInterestHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/interestHistory", params), - getForceLiquidationRecord: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/forceLiquidationRec", params), - getIsolatedAccount: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/isolated/account", params), - enableIsolatedAccount: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/isolated/account", params), - disableIsolatedAccount: (params: Record = {}) => - makeSignedRequest("DELETE", "/sapi/v1/margin/isolated/account", params), - getIsolatedMarginPairs: (params: Record = {}) => - makePublicRequest("/sapi/v1/margin/isolated/allPairs", params), - getIsolatedMarginTier: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/isolatedMarginTier", params), - getCrossMarginFee: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/crossMarginData", params), - getIsolatedMarginFee: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/isolatedMarginData", params), - getSmallLiabilityExchangeCoinList: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/exchange-small-liability", params), - smallLiabilityExchange: (params: Record = {}) => - makeSignedRequest("POST", "/sapi/v1/margin/exchange-small-liability", params), - getSmallLiabilityExchangeHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/exchange-small-liability-history", params), - getDustLog: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/dribblet", params), - getCapitalFlow: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/capital-flow", params), - getDelistSchedule: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/delist-schedule", params), - getAvailableInventory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/available-inventory", params), - getAllAssets: (params: Record = {}) => - makePublicRequest("/sapi/v1/margin/allAssets", params), - getInterestRateHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/margin/interestRateHistory", params) + borrow: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/loan", params), + repay: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/repay", params), + getAccount: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/account", params), + getMaxBorrowable: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/maxBorrowable", params), + getMaxTransferable: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/maxTransferable", params), + transfer: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/transfer", params), + getAllPairs: (params: Record = {}) => + makePublicRequest("/sapi/v1/margin/allPairs", params), + getPriceIndex: (params: Record = {}) => + makePublicRequest("/sapi/v1/margin/priceIndex", params), + newOrder: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/order", params), + cancelOrder: (params: Record = {}) => + makeSignedRequest("DELETE", "/sapi/v1/margin/order", params), + getOpenOrders: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/openOrders", params), + getAllOrders: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/allOrders", params), + getMyTrades: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/myTrades", params), + cancelAllOpenOrders: (params: Record = {}) => + makeSignedRequest("DELETE", "/sapi/v1/margin/openOrders", params), + getLoanRecord: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/loan", params), + getRepayRecord: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/repay", params), + getInterestHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/interestHistory", params), + getForceLiquidationRecord: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/forceLiquidationRec", params), + getIsolatedAccount: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/isolated/account", params), + enableIsolatedAccount: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/isolated/account", params), + disableIsolatedAccount: (params: Record = {}) => + makeSignedRequest("DELETE", "/sapi/v1/margin/isolated/account", params), + getIsolatedMarginPairs: (params: Record = {}) => + makePublicRequest("/sapi/v1/margin/isolated/allPairs", params), + getIsolatedMarginTier: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/isolatedMarginTier", params), + getCrossMarginFee: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/crossMarginData", params), + getIsolatedMarginFee: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/isolatedMarginData", params), + getSmallLiabilityExchangeCoinList: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/exchange-small-liability", params), + smallLiabilityExchange: (params: Record = {}) => + makeSignedRequest("POST", "/sapi/v1/margin/exchange-small-liability", params), + getSmallLiabilityExchangeHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/exchange-small-liability-history", params), + getDustLog: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/dribblet", params), + getCapitalFlow: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/capital-flow", params), + getDelistSchedule: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/delist-schedule", params), + getAvailableInventory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/available-inventory", params), + getAllAssets: (params: Record = {}) => + makePublicRequest("/sapi/v1/margin/allAssets", params), + getInterestRateHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/margin/interestRateHistory", params), }; -// Helper for Futures API with different base URLs -const FUTURES_USD_BASE_URL = "https://fapi.binance.com"; -const FUTURES_COIN_BASE_URL = "https://dapi.binance.com"; +const FUTURES_USD_BASE_URL = URLS.FUTURES_USD_BASE_URL; +const FUTURES_COIN_BASE_URL = URLS.FUTURES_COIN_BASE_URL; async function makeFuturesSignedRequest( - baseUrl: string, - method: "GET" | "POST" | "DELETE" | "PUT", - endpoint: string, - params: Record = {} + baseUrl: string, + method: "GET" | "POST" | "DELETE" | "PUT", + endpoint: string, + params: Record = {}, ): Promise { - const timestamp = Date.now(); - const queryParams = { ...params, timestamp }; - const queryString = new URLSearchParams( - Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [k, String(v)])) - ).toString(); - const signature = generateSignature(queryString); - const url = `${baseUrl}${endpoint}?${queryString}&signature=${signature}`; - - const response = await fetch(url, { - method, - headers: { - "X-MBX-APIKEY": API_KEY, - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); - } - - return response.json(); + const timestamp = Date.now(); + const queryParams = { ...params, timestamp }; + const queryString = new URLSearchParams( + Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [k, String(v)])), + ).toString(); + const signature = generateSignature(queryString); + const url = `${baseUrl}${endpoint}?${queryString}&signature=${signature}`; + + const response = await fetch(url, { + method, + headers: { + "X-MBX-APIKEY": API_KEY, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); + } + + return response.json(); } async function makeFuturesPublicRequest( - baseUrl: string, - endpoint: string, - params: Record = {} + baseUrl: string, + endpoint: string, + params: Record = {}, ): Promise { - const queryString = new URLSearchParams( - Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])) - ).toString(); - const url = `${baseUrl}${endpoint}${queryString ? "?" + queryString : ""}`; - - const response = await fetch(url, { - method: "GET", - headers: { "Content-Type": "application/json" } - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); - } - - return response.json(); + const queryString = new URLSearchParams( + Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])), + ).toString(); + const url = `${baseUrl}${endpoint}${queryString ? "?" + queryString : ""}`; + + const response = await fetch(url, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Binance API error: ${response.status} - ${JSON.stringify(errorData)}`); + } + + return response.json(); } // Futures USD-M client wrapper export const futuresClient = { - // Market Data - ping: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ping"), - time: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/time"), - exchangeInfo: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/exchangeInfo"), - depth: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/depth", params), - trades: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/trades", params), - historicalTrades: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/historicalTrades", params), - aggTrades: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/aggTrades", params), - klines: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/klines", params), - continuousKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/continuousKlines", params), - indexPriceKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/indexPriceKlines", params), - markPriceKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/markPriceKlines", params), - premiumIndex: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/premiumIndex", params), - fundingRate: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/fundingRate", params), - ticker24hr: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/24hr", params), - tickerPrice: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/price", params), - bookTicker: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/bookTicker", params), - openInterest: (params: Record) => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/openInterest", params), - // Account/Trade - newOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/order", params), - batchOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/batchOrders", params), - getOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/order", params), - cancelOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/order", params), - cancelAllOpenOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/allOpenOrders", params), - cancelBatchOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/batchOrders", params), - openOrders: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/openOrders", params), - allOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/allOrders", params), - balance: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/balance", params), - account: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/account", params), - leverage: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/leverage", params), - marginType: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/marginType", params), - positionMargin: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/positionMargin", params), - positionRisk: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/positionRisk", params), - userTrades: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/userTrades", params), - income: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/income", params), - commissionRate: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/commissionRate", params), - adlQuantile: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/adlQuantile", params), - forceOrders: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/forceOrders", params), - positionMode: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/positionSide/dual", params), - changePositionMode: (params: Record) => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/positionSide/dual", params), - // User Data Stream - createListenKey: () => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/listenKey", {}), - keepAliveListenKey: () => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "PUT", "/fapi/v1/listenKey", {}), - closeListenKey: () => makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/listenKey", {}) + // Market Data + ping: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ping"), + time: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/time"), + exchangeInfo: () => makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/exchangeInfo"), + depth: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/depth", params), + trades: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/trades", params), + historicalTrades: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/historicalTrades", params), + aggTrades: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/aggTrades", params), + klines: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/klines", params), + continuousKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/continuousKlines", params), + indexPriceKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/indexPriceKlines", params), + markPriceKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/markPriceKlines", params), + premiumIndex: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/premiumIndex", params), + fundingRate: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/fundingRate", params), + ticker24hr: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/24hr", params), + tickerPrice: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/price", params), + bookTicker: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/ticker/bookTicker", params), + openInterest: (params: Record) => + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/openInterest", params), + // Account/Trade + newOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/order", params), + modifyOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "PUT", "/fapi/v1/order", params), + batchOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/batchOrders", params), + getOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/order", params), + cancelOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/order", params), + cancelAllOpenOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/allOpenOrders", params), + cancelBatchOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/batchOrders", params), + openOrders: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/openOrders", params), + allOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/allOrders", params), + balance: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/balance", params), + account: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/account", params), + leverage: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/leverage", params), + marginType: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/marginType", params), + positionMargin: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/positionMargin", params), + positionRisk: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v2/positionRisk", params), + userTrades: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/userTrades", params), + income: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/income", params), + commissionRate: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/commissionRate", params), + adlQuantile: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/adlQuantile", params), + forceOrders: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/forceOrders", params), + positionMode: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/positionSide/dual", params), + changePositionMode: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/positionSide/dual", params), + multiAssetsMargin: (params: Record) => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/multiAssetsMargin", params), + // User Data Stream + createListenKey: () => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/listenKey", {}), + keepAliveListenKey: () => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "PUT", "/fapi/v1/listenKey", {}), + closeListenKey: () => + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "DELETE", "/fapi/v1/listenKey", {}), + restAPI: { + account: (p: Record = {}) => wrapData(futuresClient.account(p)), + balance: (p: Record = {}) => wrapData(futuresClient.balance(p)), + positionRisk: (p: Record = {}) => wrapData(futuresClient.positionRisk(p)), + ping: () => wrapData(futuresClient.ping()), + time: () => wrapData(futuresClient.time()), + exchangeInfo: () => wrapData(futuresClient.exchangeInfo()), + depth: (p: Record) => wrapData(futuresClient.depth(p)), + trades: (p: Record) => wrapData(futuresClient.trades(p)), + historicalTrades: (p: Record) => wrapData(futuresClient.historicalTrades(p)), + aggTrades: (p: Record) => wrapData(futuresClient.aggTrades(p)), + klines: (p: Record) => wrapData(futuresClient.klines(p)), + continuousKlines: (p: Record) => wrapData(futuresClient.continuousKlines(p)), + indexPriceKlines: (p: Record) => wrapData(futuresClient.indexPriceKlines(p)), + markPriceKlines: (p: Record) => wrapData(futuresClient.markPriceKlines(p)), + premiumIndex: (p: Record = {}) => wrapData(futuresClient.premiumIndex(p)), + fundingRate: (p: Record) => wrapData(futuresClient.fundingRate(p)), + ticker24hr: (p: Record = {}) => wrapData(futuresClient.ticker24hr(p)), + tickerPrice: (p: Record) => wrapData(futuresClient.tickerPrice(p)), + bookTicker: (p: Record = {}) => wrapData(futuresClient.bookTicker(p)), + openInterest: (p: Record) => wrapData(futuresClient.openInterest(p)), + newOrder: (p: Record) => wrapData(futuresClient.newOrder(p)), + modifyOrder: (p: Record) => wrapData(futuresClient.modifyOrder(p)), + getOrder: (p: Record) => wrapData(futuresClient.getOrder(p)), + queryOrder: (p: Record) => wrapData(futuresClient.getOrder(p)), + cancelOrder: (p: Record) => wrapData(futuresClient.cancelOrder(p)), + cancelAllOpenOrders: (p: Record = {}) => + wrapData(futuresClient.cancelAllOpenOrders(p)), + cancelBatchOrders: (p: Record) => wrapData(futuresClient.cancelBatchOrders(p)), + openOrders: (p: Record = {}) => wrapData(futuresClient.openOrders(p)), + allOrders: (p: Record) => wrapData(futuresClient.allOrders(p)), + userTrades: (p: Record) => wrapData(futuresClient.userTrades(p)), + income: (p: Record = {}) => wrapData(futuresClient.income(p)), + commissionRate: (p: Record) => wrapData(futuresClient.commissionRate(p)), + adlQuantile: (p: Record = {}) => wrapData(futuresClient.adlQuantile(p)), + forceOrders: (p: Record) => wrapData(futuresClient.forceOrders(p)), + positionMode: (p: Record = {}) => wrapData(futuresClient.positionMode(p)), + getPositionMode: (p: Record = {}) => wrapData(futuresClient.positionMode(p)), + changePositionMode: (p: Record) => wrapData(futuresClient.changePositionMode(p)), + leverage: (p: Record) => wrapData(futuresClient.leverage(p)), + changeInitialLeverage: (p: Record) => wrapData(futuresClient.leverage(p)), + marginType: (p: Record) => wrapData(futuresClient.marginType(p)), + changeMarginType: (p: Record) => wrapData(futuresClient.marginType(p)), + positionMargin: (p: Record) => wrapData(futuresClient.positionMargin(p)), + modifyIsolatedPositionMargin: (p: Record) => + wrapData(futuresClient.positionMargin(p)), + currentAllOpenOrders: (p: Record = {}) => wrapData(futuresClient.openOrders(p)), + createListenKey: () => wrapData(futuresClient.createListenKey()), + keepAliveListenKey: () => wrapData(futuresClient.keepAliveListenKey()), + closeListenKey: () => wrapData(futuresClient.closeListenKey()), + fundingInfo: () => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/fundingRate", {})), + assetIndex: (p: Record = {}) => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/assetIndex", p)), + // Aliases / additional endpoints for tool compatibility + apiTradingStatus: (p: Record = {}) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/apiTradingStatus", p), + ), + downloadIdForFuturesTransactionHistory: (p: Record = {}) => + wrapData(makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/income/asyn", p)), + leverageBracket: (p: Record = {}) => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/leverageBracket", p)), + getMultiAssetsMode: (p: Record = {}) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/multiAssetsMargin", p), + ), + getPositionMarginChangeHistory: (p: Record = {}) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/positionMargin/history", p), + ), + getPositionMarginHistory: (p: Record = {}) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "GET", "/fapi/v1/positionMargin/history", p), + ), + globalLongShortAccountRatio: (p: Record) => + wrapData( + makeFuturesPublicRequest( + FUTURES_USD_BASE_URL, + "/futures/data/globalLongShortAccountRatio", + p, + ), + ), + indexInfo: (p: Record = {}) => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/fapi/v1/indexInfo", p)), + lvtKlines: (p: Record) => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/futures/data/lvtKlines", p)), + openInterestHist: (p: Record) => + wrapData(makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/futures/data/openInterestHist", p)), + takerlongshortRatio: (p: Record) => + wrapData( + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/futures/data/takerlongshortRatio", p), + ), + tickerBookTicker: (p: Record = {}) => wrapData(futuresClient.bookTicker(p)), + topLongShortAccountRatio: (p: Record) => + wrapData( + makeFuturesPublicRequest(FUTURES_USD_BASE_URL, "/futures/data/topLongShortAccountRatio", p), + ), + topLongShortPositionRatio: (p: Record) => + wrapData( + makeFuturesPublicRequest( + FUTURES_USD_BASE_URL, + "/futures/data/topLongShortPositionRatio", + p, + ), + ), + placeMultipleOrders: (p: Record) => wrapData(futuresClient.batchOrders(p)), + cancelMultipleOrders: (p: Record) => wrapData(futuresClient.cancelBatchOrders(p)), + changeMultiAssetsMode: (p: Record) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/multiAssetsMargin", p), + ), + autoCancelAllOpenOrders: (p: Record) => + wrapData( + makeFuturesSignedRequest(FUTURES_USD_BASE_URL, "POST", "/fapi/v1/countdownCancelAll", p), + ), + queryCurrentOpenOrder: (p: Record) => wrapData(futuresClient.getOrder(p)), + currentOpenOrder: (p: Record = {}) => wrapData(futuresClient.openOrders(p)), + renewListenKey: () => wrapData(futuresClient.keepAliveListenKey()), + }, }; // Futures COIN-M client wrapper (delivery) export const deliveryClient = { - // Market Data - ping: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ping"), - time: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/time"), - exchangeInfo: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/exchangeInfo"), - depth: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/depth", params), - trades: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/trades", params), - historicalTrades: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/historicalTrades", params), - aggTrades: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/aggTrades", params), - klines: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/klines", params), - continuousKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/continuousKlines", params), - indexPriceKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/indexPriceKlines", params), - markPriceKlines: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/markPriceKlines", params), - premiumIndex: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/premiumIndex", params), - fundingRate: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/fundingRate", params), - ticker24hr: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/24hr", params), - tickerPrice: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/price", params), - bookTicker: (params: Record = {}) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/bookTicker", params), - openInterest: (params: Record) => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/openInterest", params), - // Account/Trade - newOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/order", params), - batchOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/batchOrders", params), - getOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/order", params), - cancelOrder: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/order", params), - cancelAllOpenOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/allOpenOrders", params), - cancelBatchOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/batchOrders", params), - openOrders: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/openOrders", params), - allOrders: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/allOrders", params), - balance: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/balance", params), - account: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/account", params), - leverage: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/leverage", params), - marginType: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/marginType", params), - positionMargin: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/positionMargin", params), - positionRisk: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/positionRisk", params), - userTrades: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/userTrades", params), - income: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/income", params), - commissionRate: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/commissionRate", params), - adlQuantile: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/adlQuantile", params), - forceOrders: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/forceOrders", params), - positionMode: (params: Record = {}) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/positionSide/dual", params), - changePositionMode: (params: Record) => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/positionSide/dual", params), - // User Data Stream - createListenKey: () => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/listenKey", {}), - keepAliveListenKey: () => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "PUT", "/dapi/v1/listenKey", {}), - closeListenKey: () => makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/listenKey", {}) + // Market Data + ping: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ping"), + time: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/time"), + exchangeInfo: () => makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/exchangeInfo"), + depth: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/depth", params), + trades: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/trades", params), + historicalTrades: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/historicalTrades", params), + aggTrades: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/aggTrades", params), + klines: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/klines", params), + continuousKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/continuousKlines", params), + indexPriceKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/indexPriceKlines", params), + markPriceKlines: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/markPriceKlines", params), + premiumIndex: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/premiumIndex", params), + fundingRate: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/fundingRate", params), + ticker24hr: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/24hr", params), + tickerPrice: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/price", params), + bookTicker: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/ticker/bookTicker", params), + openInterest: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/openInterest", params), + openInterestHist: (params: Record) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/openInterestHist", params), + leverageBracket: (params: Record = {}) => + makeFuturesPublicRequest(FUTURES_COIN_BASE_URL, "/dapi/v1/leverageBracket", params), + // Account/Trade + newOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/order", params), + batchOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/batchOrders", params), + getOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/order", params), + cancelOrder: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/order", params), + cancelAllOpenOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/allOpenOrders", params), + cancelBatchOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/batchOrders", params), + openOrders: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/openOrders", params), + allOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/allOrders", params), + balance: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/balance", params), + account: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/account", params), + leverage: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/leverage", params), + marginType: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/marginType", params), + positionMargin: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/positionMargin", params), + positionRisk: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/positionRisk", params), + userTrades: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/userTrades", params), + income: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/income", params), + commissionRate: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/commissionRate", params), + adlQuantile: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/adlQuantile", params), + forceOrders: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/forceOrders", params), + positionMode: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "GET", "/dapi/v1/positionSide/dual", params), + changePositionMode: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/positionSide/dual", params), + // User Data Stream + createListenKey: () => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/listenKey", {}), + keepAliveListenKey: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "PUT", "/dapi/v1/listenKey", params), + closeListenKey: (params: Record = {}) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "DELETE", "/dapi/v1/listenKey", params), + autoCancelAllOpenOrders: (params: Record) => + makeFuturesSignedRequest(FUTURES_COIN_BASE_URL, "POST", "/dapi/v1/countdownCancelAll", params), + restAPI: { + account: (p: Record = {}) => wrapData(deliveryClient.account(p)), + balance: (p: Record = {}) => wrapData(deliveryClient.balance(p)), + positionRisk: (p: Record = {}) => wrapData(deliveryClient.positionRisk(p)), + ping: () => wrapData(deliveryClient.ping()), + time: () => wrapData(deliveryClient.time()), + exchangeInfo: () => wrapData(deliveryClient.exchangeInfo()), + depth: (p: Record) => wrapData(deliveryClient.depth(p)), + trades: (p: Record) => wrapData(deliveryClient.trades(p)), + historicalTrades: (p: Record) => wrapData(deliveryClient.historicalTrades(p)), + aggTrades: (p: Record) => wrapData(deliveryClient.aggTrades(p)), + klines: (p: Record) => wrapData(deliveryClient.klines(p)), + continuousKlines: (p: Record) => wrapData(deliveryClient.continuousKlines(p)), + indexPriceKlines: (p: Record) => wrapData(deliveryClient.indexPriceKlines(p)), + markPriceKlines: (p: Record) => wrapData(deliveryClient.markPriceKlines(p)), + premiumIndex: (p: Record = {}) => wrapData(deliveryClient.premiumIndex(p)), + fundingRate: (p: Record) => wrapData(deliveryClient.fundingRate(p)), + ticker24hr: (p: Record = {}) => wrapData(deliveryClient.ticker24hr(p)), + tickerPrice: (p: Record) => wrapData(deliveryClient.tickerPrice(p)), + bookTicker: (p: Record = {}) => wrapData(deliveryClient.bookTicker(p)), + tickerBookTicker: (p: Record = {}) => wrapData(deliveryClient.bookTicker(p)), + openInterest: (p: Record) => wrapData(deliveryClient.openInterest(p)), + openInterestHist: (p: Record) => wrapData(deliveryClient.openInterestHist(p)), + leverageBracket: (p: Record = {}) => wrapData(deliveryClient.leverageBracket(p)), + newOrder: (p: Record) => wrapData(deliveryClient.newOrder(p)), + getOrder: (p: Record) => wrapData(deliveryClient.getOrder(p)), + queryOrder: (p: Record) => wrapData(deliveryClient.getOrder(p)), + cancelOrder: (p: Record) => wrapData(deliveryClient.cancelOrder(p)), + cancelAllOpenOrders: (p: Record = {}) => + wrapData(deliveryClient.cancelAllOpenOrders(p)), + cancelBatchOrders: (p: Record) => wrapData(deliveryClient.cancelBatchOrders(p)), + cancelMultipleOrders: (p: Record) => wrapData(deliveryClient.cancelBatchOrders(p)), + openOrders: (p: Record = {}) => wrapData(deliveryClient.openOrders(p)), + currentAllOpenOrders: (p: Record = {}) => wrapData(deliveryClient.openOrders(p)), + allOrders: (p: Record) => wrapData(deliveryClient.allOrders(p)), + currentOpenOrder: (p: Record) => wrapData(deliveryClient.getOrder(p)), + userTrades: (p: Record) => wrapData(deliveryClient.userTrades(p)), + income: (p: Record = {}) => wrapData(deliveryClient.income(p)), + commissionRate: (p: Record) => wrapData(deliveryClient.commissionRate(p)), + adlQuantile: (p: Record = {}) => wrapData(deliveryClient.adlQuantile(p)), + forceOrders: (p: Record) => wrapData(deliveryClient.forceOrders(p)), + positionMode: (p: Record = {}) => wrapData(deliveryClient.positionMode(p)), + getPositionMode: (p: Record = {}) => wrapData(deliveryClient.positionMode(p)), + changePositionMode: (p: Record) => wrapData(deliveryClient.changePositionMode(p)), + leverage: (p: Record) => wrapData(deliveryClient.leverage(p)), + changeInitialLeverage: (p: Record) => wrapData(deliveryClient.leverage(p)), + marginType: (p: Record) => wrapData(deliveryClient.marginType(p)), + changeMarginType: (p: Record) => wrapData(deliveryClient.marginType(p)), + positionMargin: (p: Record) => wrapData(deliveryClient.positionMargin(p)), + modifyIsolatedPositionMargin: (p: Record) => + wrapData(deliveryClient.positionMargin(p)), + batchOrders: (p: Record) => wrapData(deliveryClient.batchOrders(p)), + placeMultipleOrders: (p: Record) => wrapData(deliveryClient.batchOrders(p)), + autoCancelAllOpenOrders: (p: Record) => + wrapData(deliveryClient.autoCancelAllOpenOrders(p)), + createListenKey: () => wrapData(deliveryClient.createListenKey()), + keepAliveListenKey: () => wrapData(deliveryClient.keepAliveListenKey()), + renewListenKey: (p: Record = {}) => wrapData(deliveryClient.keepAliveListenKey(p)), + closeListenKey: (p: Record = {}) => wrapData(deliveryClient.closeListenKey(p)), + }, }; // Sub-Account client wrapper (using REST API) export const subAccountApiClient = { - createVirtualSubAccount: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/virtualSubAccount", params), - getSubAccountList: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/list", params), - getSubAccountSpotSummary: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/spotSummary", params), - getSubAccountStatus: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/status", params), - getSubAccountAssets: (params: Record) => - makeSignedRequest("GET", "/sapi/v3/sub-account/assets", params), - enableMarginForSubAccount: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/margin/enable", params), - enableFuturesForSubAccount: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/futures/enable", params), - getSubAccountMarginSummary: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/margin/accountSummary", params), - getSubAccountFuturesSummary: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v2/sub-account/futures/accountSummary", params), - getSubAccountFuturesPositionRisk: (params: Record) => - makeSignedRequest("GET", "/sapi/v2/sub-account/futures/positionRisk", params), - transferToSubAccount: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/transfer/subToSub", params), - transferToMaster: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/transfer/subToMaster", params), - subAccountUniversalTransfer: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/universalTransfer", params), - getSubAccountUniversalTransferHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/universalTransfer", params), - getSubAccountTransferHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/sub-account/sub/transfer/history", params), - getSubAccountDepositAddress: (params: Record) => - makeSignedRequest("GET", "/sapi/v1/capital/deposit/subAddress", params), - getSubAccountDepositHistory: (params: Record = {}) => - makeSignedRequest("GET", "/sapi/v1/capital/deposit/subHisrec", params), - createSubAccountApiKey: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params), - deleteSubAccountApiKey: (params: Record) => - makeSignedRequest("DELETE", "/sapi/v1/sub-account/subAccountApi/ipRestriction/ipList", params), - getSubAccountApiKeyIpRestriction: (params: Record) => - makeSignedRequest("GET", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params), - updateSubAccountApiKeyIpRestriction: (params: Record) => - makeSignedRequest("POST", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params) + createVirtualSubAccount: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/virtualSubAccount", params), + getSubAccountList: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/list", params), + getSubAccountSpotSummary: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/spotSummary", params), + getSubAccountStatus: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/status", params), + getSubAccountAssets: (params: Record) => + makeSignedRequest("GET", "/sapi/v3/sub-account/assets", params), + enableMarginForSubAccount: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/margin/enable", params), + enableFuturesForSubAccount: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/futures/enable", params), + getSubAccountMarginSummary: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/margin/accountSummary", params), + getSubAccountFuturesSummary: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v2/sub-account/futures/accountSummary", params), + getSubAccountFuturesPositionRisk: (params: Record) => + makeSignedRequest("GET", "/sapi/v2/sub-account/futures/positionRisk", params), + transferToSubAccount: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/transfer/subToSub", params), + transferToMaster: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/transfer/subToMaster", params), + subAccountUniversalTransfer: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/universalTransfer", params), + getSubAccountUniversalTransferHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/universalTransfer", params), + getSubAccountTransferHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/sub-account/sub/transfer/history", params), + getSubAccountDepositAddress: (params: Record) => + makeSignedRequest("GET", "/sapi/v1/capital/deposit/subAddress", params), + getSubAccountDepositHistory: (params: Record = {}) => + makeSignedRequest("GET", "/sapi/v1/capital/deposit/subHisrec", params), + createSubAccountApiKey: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params), + deleteSubAccountApiKey: (params: Record) => + makeSignedRequest("DELETE", "/sapi/v1/sub-account/subAccountApi/ipRestriction/ipList", params), + getSubAccountApiKeyIpRestriction: (params: Record) => + makeSignedRequest("GET", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params), + updateSubAccountApiKeyIpRestriction: (params: Record) => + makeSignedRequest("POST", "/sapi/v1/sub-account/subAccountApi/ipRestriction", params), }; -// Options client wrapper -const OPTIONS_BASE_URL = "https://eapi.binance.com"; +const OPTIONS_BASE_URL = URLS.OPTIONS_BASE_URL; export const optionsClient = { - // Market Data - ping: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/ping"), - time: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/time"), - exchangeInfo: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/exchangeInfo"), - depth: (params: Record) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/depth", params), - trades: (params: Record) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/trades", params), - klines: (params: Record) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/klines", params), - mark: (params: Record = {}) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/mark", params), - ticker: (params: Record = {}) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/ticker", params), - index: (params: Record) => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/index", params), - // Account/Trade - newOrder: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/order", params), - batchOrders: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/batchOrders", params), - cancelOrder: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/order", params), - cancelBatchOrders: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/batchOrders", params), - cancelAllOrders: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/allOpenOrders", params), - getOrder: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/order", params), - openOrders: (params: Record = {}) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/openOrders", params), - historyOrders: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/historyOrders", params), - position: (params: Record = {}) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/position", params), - userTrades: (params: Record) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/userTrades", params), - account: (params: Record = {}) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/account", params), - exerciseRecord: (params: Record = {}) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/exerciseRecord", params), - bill: (params: Record = {}) => makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/bill", params), - // User Data Stream - createListenKey: () => makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/listenKey", {}), - keepAliveListenKey: () => makeFuturesSignedRequest(OPTIONS_BASE_URL, "PUT", "/eapi/v1/listenKey", {}), - closeListenKey: () => makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/listenKey", {}) + // Market Data + ping: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/ping"), + time: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/time"), + exchangeInfo: () => makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/exchangeInfo"), + depth: (params: Record) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/depth", params), + trades: (params: Record) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/trades", params), + klines: (params: Record) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/klines", params), + mark: (params: Record = {}) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/mark", params), + ticker: (params: Record = {}) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/ticker", params), + index: (params: Record) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/index", params), + // Account/Trade + newOrder: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/order", params), + batchOrders: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/batchOrders", params), + cancelOrder: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/order", params), + cancelBatchOrders: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/batchOrders", params), + cancelAllOrders: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/allOpenOrders", params), + getOrder: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/order", params), + openOrders: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/openOrders", params), + historyOrders: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/historyOrders", params), + position: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/position", params), + userTrades: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/userTrades", params), + account: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/account", params), + exerciseRecord: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/exerciseRecord", params), + openInterest: (params: Record = {}) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/openInterest", params), + bill: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/bill", params), + incomeAsyn: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/incomeAsyn", params), + incomeAsynId: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "GET", "/eapi/v1/incomeAsynId", params), + historicalTrades: (params: Record) => + makeFuturesPublicRequest(OPTIONS_BASE_URL, "/eapi/v1/historicalTrades", params), + cancelAllOpenOrdersByUnderlying: (params: Record) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/allOpenOrders", params), + // User Data Stream + createListenKey: () => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "POST", "/eapi/v1/listenKey", {}), + keepAliveListenKey: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "PUT", "/eapi/v1/listenKey", params), + closeListenKey: (params: Record = {}) => + makeFuturesSignedRequest(OPTIONS_BASE_URL, "DELETE", "/eapi/v1/listenKey", params), }; diff --git a/src/config/binanceUsClient.ts b/src/config/binanceUsClient.ts index a9c45e20..0be12dfa 100644 --- a/src/config/binanceUsClient.ts +++ b/src/config/binanceUsClient.ts @@ -3,15 +3,15 @@ import crypto from "crypto"; /** * Binance.US API Client Configuration - * + * * Base URLs: * - REST API: https://api.binance.us * - WebSocket: wss://stream.binance.us:9443 - * + * * Authentication: * - API Key passed via X-MBX-APIKEY header * - Signature generated using HMAC SHA256 - * + * * Key Differences from Binance.com: * - US regulatory compliance * - No futures, margin, or lending @@ -37,205 +37,212 @@ const BASE_URL = BINANCE_US_CONFIG.BASE_URL; /** Rate limit information from API response headers */ export interface RateLimitInfo { - usedWeight: number; - weightLimit: number; - orderCount?: number; - retryAfter?: number; + usedWeight: number; + weightLimit: number; + orderCount?: number; + retryAfter?: number; } /** API response wrapper with rate limit info */ export interface BinanceUsResponse { - data: T; - rateLimitInfo?: RateLimitInfo; + data: T; + rateLimitInfo?: RateLimitInfo; } /** Ping response (empty object) */ -export interface PingResponse {} +export type PingResponse = Record; /** Server time response */ export interface ServerTimeResponse { - serverTime: number; + serverTime: number; } /** System status response */ export interface SystemStatusResponse { - status: 0 | 1; // 0: normal, 1: system maintenance + status: 0 | 1; // 0: normal, 1: system maintenance } /** Symbol information in exchange info */ export interface SymbolInfo { - symbol: string; - status: "PRE_TRADING" | "TRADING" | "POST_TRADING" | "END_OF_DAY" | "HALT" | "AUCTION_MATCH" | "BREAK"; - baseAsset: string; - baseAssetPrecision: number; - quoteAsset: string; - quotePrecision: number; - quoteAssetPrecision: number; - baseCommissionPrecision: number; - quoteCommissionPrecision: number; - orderTypes: string[]; - icebergAllowed: boolean; - ocoAllowed: boolean; - quoteOrderQtyMarketAllowed: boolean; - allowTrailingStop: boolean; - cancelReplaceAllowed: boolean; - isSpotTradingAllowed: boolean; - isMarginTradingAllowed: boolean; - filters: any[]; - permissions: string[]; + symbol: string; + status: + | "PRE_TRADING" + | "TRADING" + | "POST_TRADING" + | "END_OF_DAY" + | "HALT" + | "AUCTION_MATCH" + | "BREAK"; + baseAsset: string; + baseAssetPrecision: number; + quoteAsset: string; + quotePrecision: number; + quoteAssetPrecision: number; + baseCommissionPrecision: number; + quoteCommissionPrecision: number; + orderTypes: string[]; + icebergAllowed: boolean; + ocoAllowed: boolean; + quoteOrderQtyMarketAllowed: boolean; + allowTrailingStop: boolean; + cancelReplaceAllowed: boolean; + isSpotTradingAllowed: boolean; + isMarginTradingAllowed: boolean; + filters: any[]; + permissions: string[]; } /** Exchange information response */ export interface ExchangeInfoResponse { - timezone: string; - serverTime: number; - rateLimits: any[]; - exchangeFilters: any[]; - symbols: SymbolInfo[]; - permissions: string[]; - defaultSelfTradePreventionMode?: string; - allowedSelfTradePreventionModes?: string[]; + timezone: string; + serverTime: number; + rateLimits: any[]; + exchangeFilters: any[]; + symbols: SymbolInfo[]; + permissions: string[]; + defaultSelfTradePreventionMode?: string; + allowedSelfTradePreventionModes?: string[]; } /** Order book response */ export interface OrderBookResponse { - lastUpdateId: number; - bids: [string, string][]; // [price, quantity][] - asks: [string, string][]; // [price, quantity][] + lastUpdateId: number; + bids: [string, string][]; // [price, quantity][] + asks: [string, string][]; // [price, quantity][] } /** Trade response */ export interface TradeResponse { - id: number; - price: string; - qty: string; - quoteQty: string; - time: number; - isBuyerMaker: boolean; - isBestMatch: boolean; + id: number; + price: string; + qty: string; + quoteQty: string; + time: number; + isBuyerMaker: boolean; + isBestMatch: boolean; } /** Aggregate trade response */ export interface AggTradeResponse { - a: number; // Aggregate tradeId - p: string; // Price - q: string; // Quantity - f: number; // First tradeId - l: number; // Last tradeId - T: number; // Timestamp - m: boolean; // Was the buyer the maker? - M: boolean; // Was the trade the best price match? + a: number; // Aggregate tradeId + p: string; // Price + q: string; // Quantity + f: number; // First tradeId + l: number; // Last tradeId + T: number; // Timestamp + m: boolean; // Was the buyer the maker? + M: boolean; // Was the trade the best price match? } /** Formatted aggregate trade (human-readable) */ export interface FormattedAggTrade { - aggregateTradeId: number; - price: string; - quantity: string; - firstTradeId: number; - lastTradeId: number; - timestamp: number; - timestampISO: string; - isBuyerMaker: boolean; - isBestMatch: boolean; + aggregateTradeId: number; + price: string; + quantity: string; + firstTradeId: number; + lastTradeId: number; + timestamp: number; + timestampISO: string; + isBuyerMaker: boolean; + isBestMatch: boolean; } /** Raw kline data (array format from API) */ export type KlineRaw = [ - number, // 0: Open time - string, // 1: Open price - string, // 2: High price - string, // 3: Low price - string, // 4: Close price - string, // 5: Volume - number, // 6: Close time - string, // 7: Quote asset volume - number, // 8: Number of trades - string, // 9: Taker buy base asset volume - string, // 10: Taker buy quote asset volume - string // 11: Ignore + number, // 0: Open time + string, // 1: Open price + string, // 2: High price + string, // 3: Low price + string, // 4: Close price + string, // 5: Volume + number, // 6: Close time + string, // 7: Quote asset volume + number, // 8: Number of trades + string, // 9: Taker buy base asset volume + string, // 10: Taker buy quote asset volume + string, // 11: Ignore ]; /** Formatted kline (human-readable) */ export interface FormattedKline { - openTime: number; - openTimeISO: string; - open: string; - high: string; - low: string; - close: string; - volume: string; - closeTime: number; - closeTimeISO: string; - quoteAssetVolume: string; - numberOfTrades: number; - takerBuyBaseVolume: string; - takerBuyQuoteVolume: string; + openTime: number; + openTimeISO: string; + open: string; + high: string; + low: string; + close: string; + volume: string; + closeTime: number; + closeTimeISO: string; + quoteAssetVolume: string; + numberOfTrades: number; + takerBuyBaseVolume: string; + takerBuyQuoteVolume: string; } /** Average price response */ export interface AvgPriceResponse { - mins: number; - price: string; + mins: number; + price: string; } /** Ticker price response */ export interface TickerPriceResponse { - symbol: string; - price: string; + symbol: string; + price: string; } /** Book ticker response */ export interface BookTickerResponse { - symbol: string; - bidPrice: string; - bidQty: string; - askPrice: string; - askQty: string; + symbol: string; + bidPrice: string; + bidQty: string; + askPrice: string; + askQty: string; } /** 24hr ticker response */ export interface Ticker24hrResponse { - symbol: string; - priceChange: string; - priceChangePercent: string; - weightedAvgPrice: string; - prevClosePrice: string; - lastPrice: string; - lastQty: string; - bidPrice: string; - bidQty: string; - askPrice: string; - askQty: string; - openPrice: string; - highPrice: string; - lowPrice: string; - volume: string; - quoteVolume: string; - openTime: number; - closeTime: number; - firstId: number; - lastId: number; - count: number; + symbol: string; + priceChange: string; + priceChangePercent: string; + weightedAvgPrice: string; + prevClosePrice: string; + lastPrice: string; + lastQty: string; + bidPrice: string; + bidQty: string; + askPrice: string; + askQty: string; + openPrice: string; + highPrice: string; + lowPrice: string; + volume: string; + quoteVolume: string; + openTime: number; + closeTime: number; + firstId: number; + lastId: number; + count: number; } /** Rolling window ticker response */ export interface RollingWindowTickerResponse { - symbol: string; - priceChange: string; - priceChangePercent: string; - weightedAvgPrice: string; - openPrice: string; - highPrice: string; - lowPrice: string; - lastPrice: string; - volume: string; - quoteVolume: string; - openTime: number; - closeTime: number; - firstId: number; - lastId: number; - count: number; + symbol: string; + priceChange: string; + priceChangePercent: string; + weightedAvgPrice: string; + openPrice: string; + highPrice: string; + lowPrice: string; + lastPrice: string; + volume: string; + quoteVolume: string; + openTime: number; + closeTime: number; + firstId: number; + lastId: number; + count: number; } // ============================================================================ @@ -244,39 +251,39 @@ export interface RollingWindowTickerResponse { /** Custom error class for Binance.US API errors */ export class BinanceUsApiError extends Error { - constructor( - public readonly code: number, - message: string, - public readonly httpStatus: number, - public readonly rateLimitInfo?: RateLimitInfo - ) { - super(message); - this.name = "BinanceUsApiError"; - } + constructor( + public readonly code: number, + message: string, + public readonly httpStatus: number, + public readonly rateLimitInfo?: RateLimitInfo, + ) { + super(message); + this.name = "BinanceUsApiError"; + } } /** Rate limit error (HTTP 429) */ export class RateLimitError extends BinanceUsApiError { - constructor( - message: string, - public readonly retryAfter: number, - rateLimitInfo?: RateLimitInfo - ) { - super(-1003, message, 429, rateLimitInfo); - this.name = "RateLimitError"; - } + constructor( + message: string, + public readonly retryAfter: number, + rateLimitInfo?: RateLimitInfo, + ) { + super(-1003, message, 429, rateLimitInfo); + this.name = "RateLimitError"; + } } /** IP ban error (HTTP 418) */ export class IpBanError extends BinanceUsApiError { - constructor( - message: string, - public readonly retryAfter: number, - rateLimitInfo?: RateLimitInfo - ) { - super(-1003, message, 418, rateLimitInfo); - this.name = "IpBanError"; - } + constructor( + message: string, + public readonly retryAfter: number, + rateLimitInfo?: RateLimitInfo, + ) { + super(-1003, message, 418, rateLimitInfo); + this.name = "IpBanError"; + } } // ============================================================================ @@ -287,96 +294,94 @@ export class IpBanError extends BinanceUsApiError { * Generate HMAC SHA256 signature for Binance.US API requests */ export function generateSignature(queryString: string): string { - return crypto - .createHmac("sha256", API_SECRET) - .update(queryString) - .digest("hex"); + return crypto.createHmac("sha256", API_SECRET).update(queryString).digest("hex"); } /** * Build query string from parameters object */ export function buildQueryString(params: Record): string { - const filteredParams = Object.entries(params) - .filter(([_, value]) => value !== undefined && value !== null) - .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`) - .join("&"); - return filteredParams; + const filteredParams = Object.entries(params) + .filter(([_, value]) => value !== undefined && value !== null) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`) + .join("&"); + + return filteredParams; } /** * Check if API credentials are configured */ export function hasApiCredentials(): boolean { - return !!(API_KEY && API_SECRET); + return !!(API_KEY && API_SECRET); } /** * Check if API key is configured (for MARKET_DATA requests) */ export function hasApiKey(): boolean { - return !!API_KEY; + return !!API_KEY; } /** * Get current timestamp in milliseconds */ export function getTimestamp(): number { - return Date.now(); + return Date.now(); } /** * Parse rate limit info from response headers */ function parseRateLimitInfo(headers: Headers): RateLimitInfo | undefined { - const usedWeight = headers.get("X-MBX-USED-WEIGHT-1M"); - const retryAfter = headers.get("Retry-After"); - - if (!usedWeight && !retryAfter) return undefined; - - return { - usedWeight: usedWeight ? parseInt(usedWeight, 10) : 0, - weightLimit: 1200, // Default weight limit per minute - retryAfter: retryAfter ? parseInt(retryAfter, 10) : undefined, - }; + const usedWeight = headers.get("X-MBX-USED-WEIGHT-1M"); + const retryAfter = headers.get("Retry-After"); + + if (!usedWeight && !retryAfter) return undefined; + + return { + usedWeight: usedWeight ? parseInt(usedWeight, 10) : 0, + weightLimit: 1200, // Default weight limit per minute + retryAfter: retryAfter ? parseInt(retryAfter, 10) : undefined, + }; } /** * Format a kline array into a readable object */ export function formatKline(kline: KlineRaw): FormattedKline { - return { - openTime: kline[0], - openTimeISO: new Date(kline[0]).toISOString(), - open: kline[1], - high: kline[2], - low: kline[3], - close: kline[4], - volume: kline[5], - closeTime: kline[6], - closeTimeISO: new Date(kline[6]).toISOString(), - quoteAssetVolume: kline[7], - numberOfTrades: kline[8], - takerBuyBaseVolume: kline[9], - takerBuyQuoteVolume: kline[10], - }; + return { + openTime: kline[0], + openTimeISO: new Date(kline[0]).toISOString(), + open: kline[1], + high: kline[2], + low: kline[3], + close: kline[4], + volume: kline[5], + closeTime: kline[6], + closeTimeISO: new Date(kline[6]).toISOString(), + quoteAssetVolume: kline[7], + numberOfTrades: kline[8], + takerBuyBaseVolume: kline[9], + takerBuyQuoteVolume: kline[10], + }; } /** * Format an aggregate trade into a readable object */ export function formatAggTrade(trade: AggTradeResponse): FormattedAggTrade { - return { - aggregateTradeId: trade.a, - price: trade.p, - quantity: trade.q, - firstTradeId: trade.f, - lastTradeId: trade.l, - timestamp: trade.T, - timestampISO: new Date(trade.T).toISOString(), - isBuyerMaker: trade.m, - isBestMatch: trade.M, - }; + return { + aggregateTradeId: trade.a, + price: trade.p, + quantity: trade.q, + firstTradeId: trade.f, + lastTradeId: trade.l, + timestamp: trade.T, + timestampISO: new Date(trade.T).toISOString(), + isBuyerMaker: trade.m, + isBestMatch: trade.M, + }; } // ============================================================================ @@ -391,206 +396,212 @@ export function formatAggTrade(trade: AggTradeResponse): FormattedAggTrade { * @param recvWindow Optional receive window (default 5000, max 60000) */ export async function makeSignedRequest( - method: "GET" | "POST" | "PUT" | "DELETE", - endpoint: string, - params: Record = {}, - recvWindow: number = BINANCE_US_CONFIG.DEFAULT_RECV_WINDOW + method: "GET" | "POST" | "PUT" | "DELETE", + endpoint: string, + params: Record = {}, + recvWindow: number = BINANCE_US_CONFIG.DEFAULT_RECV_WINDOW, ): Promise { - // Validate credentials - if (!hasApiCredentials()) { - throw new BinanceUsApiError( - -2015, - "API credentials required. Set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables.", - 401 - ); - } - - // Validate recvWindow - if (recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { - recvWindow = BINANCE_US_CONFIG.MAX_RECV_WINDOW; - } - - // Add timestamp and recvWindow to params - const timestamp = Date.now(); - const paramsWithTimestamp = { ...params, timestamp, recvWindow }; - - // Build query string and generate signature - const queryString = buildQueryString(paramsWithTimestamp); - const signature = generateSignature(queryString); - const signedQueryString = `${queryString}&signature=${signature}`; - - // Build URL and headers - const url = method === "GET" || method === "DELETE" - ? `${BASE_URL}${endpoint}?${signedQueryString}` - : `${BASE_URL}${endpoint}`; - - const headers: HeadersInit = { - "X-MBX-APIKEY": API_KEY, - "Content-Type": "application/x-www-form-urlencoded" + // Validate credentials + if (!hasApiCredentials()) { + throw new BinanceUsApiError( + -2015, + "API credentials required. Set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables.", + 401, + ); + } + + // Validate recvWindow + if (recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { + recvWindow = BINANCE_US_CONFIG.MAX_RECV_WINDOW; + } + + // Add timestamp and recvWindow to params + const timestamp = Date.now(); + const paramsWithTimestamp = { ...params, timestamp, recvWindow }; + + // Build query string and generate signature + const queryString = buildQueryString(paramsWithTimestamp); + const signature = generateSignature(queryString); + const signedQueryString = `${queryString}&signature=${signature}`; + + // Build URL and headers + const url = + method === "GET" || method === "DELETE" + ? `${BASE_URL}${endpoint}?${signedQueryString}` + : `${BASE_URL}${endpoint}`; + + const headers: Record = { + "X-MBX-APIKEY": API_KEY, + "Content-Type": "application/x-www-form-urlencoded", + }; + + const fetchOptions: RequestInit = { + method, + headers, + }; + + // For POST and PUT requests, send data in body + if (method === "POST" || method === "PUT") { + fetchOptions.body = signedQueryString; + } + + const response = await fetch(url, fetchOptions); + const rateLimitInfo = parseRateLimitInfo(response.headers); + + // Handle rate limiting (429) + if (response.status === 429) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); + throw new RateLimitError( + `Rate limit exceeded. Retry after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + // Handle IP ban (418) + if (response.status === 418) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); + throw new IpBanError( + `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + if (!response.ok) { + const errorData = (await response.json().catch(() => ({ msg: response.statusText }))) as { + code?: number; + msg?: string; }; - - const fetchOptions: RequestInit = { - method, - headers - }; - - // For POST and PUT requests, send data in body - if (method === "POST" || method === "PUT") { - fetchOptions.body = signedQueryString; - } - - const response = await fetch(url, fetchOptions); - const rateLimitInfo = parseRateLimitInfo(response.headers); - - // Handle rate limiting (429) - if (response.status === 429) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); - throw new RateLimitError( - `Rate limit exceeded. Retry after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - // Handle IP ban (418) - if (response.status === 418) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); - throw new IpBanError( - `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - if (!response.ok) { - const errorData = await response.json().catch(() => ({ msg: response.statusText })); - throw new BinanceUsApiError( - errorData.code || response.status, - errorData.msg || response.statusText, - response.status, - rateLimitInfo - ); - } - - return response.json(); + throw new BinanceUsApiError( + errorData.code ?? response.status, + errorData.msg ?? response.statusText, + response.status, + rateLimitInfo, + ); + } + + return response.json(); } /** * Make a public (unsigned) request to Binance.US API */ export async function makePublicRequest( - method: "GET", - endpoint: string, - params: Record = {} + method: "GET", + endpoint: string, + params: Record = {}, ): Promise { - const queryString = buildQueryString(params); - const url = queryString - ? `${BASE_URL}${endpoint}?${queryString}` - : `${BASE_URL}${endpoint}`; - - const response = await fetch(url, { method }); - const rateLimitInfo = parseRateLimitInfo(response.headers); - - // Handle rate limiting (429) - if (response.status === 429) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); - throw new RateLimitError( - `Rate limit exceeded. Retry after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - // Handle IP ban (418) - if (response.status === 418) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); - throw new IpBanError( - `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - if (!response.ok) { - const errorData = await response.json().catch(() => ({ msg: response.statusText })); - throw new BinanceUsApiError( - errorData.code || response.status, - errorData.msg || response.statusText, - response.status, - rateLimitInfo - ); - } - - return response.json(); + const queryString = buildQueryString(params); + const url = queryString ? `${BASE_URL}${endpoint}?${queryString}` : `${BASE_URL}${endpoint}`; + + const response = await fetch(url, { method }); + const rateLimitInfo = parseRateLimitInfo(response.headers); + + // Handle rate limiting (429) + if (response.status === 429) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); + throw new RateLimitError( + `Rate limit exceeded. Retry after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + // Handle IP ban (418) + if (response.status === 418) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); + throw new IpBanError( + `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + if (!response.ok) { + const errorData = (await response.json().catch(() => ({ msg: response.statusText }))) as { + code?: number; + msg?: string; + }; + throw new BinanceUsApiError( + errorData.code ?? response.status, + errorData.msg ?? response.statusText, + response.status, + rateLimitInfo, + ); + } + + return response.json(); } export const binanceUsConfig = { - apiKey: API_KEY, - apiSecret: API_SECRET, - baseUrl: BASE_URL, - wsUrl: BINANCE_US_CONFIG.WS_URL + apiKey: API_KEY, + apiSecret: API_SECRET, + baseUrl: BASE_URL, + wsUrl: BINANCE_US_CONFIG.WS_URL, }; /** * Make a MARKET_DATA request (requires API key but no signature) */ export async function makeMarketDataRequest( - method: "GET", - endpoint: string, - params: Record = {} + method: "GET", + endpoint: string, + params: Record = {}, ): Promise { - // Validate API key - if (!hasApiKey()) { - throw new BinanceUsApiError( - -2015, - "API key required for MARKET_DATA endpoints. Set BINANCE_US_API_KEY environment variable.", - 401 - ); - } - - const queryString = buildQueryString(params); - const url = queryString - ? `${BASE_URL}${endpoint}?${queryString}` - : `${BASE_URL}${endpoint}`; - - const headers: HeadersInit = { - "X-MBX-APIKEY": API_KEY + // Validate API key + if (!hasApiKey()) { + throw new BinanceUsApiError( + -2015, + "API key required for MARKET_DATA endpoints. Set BINANCE_US_API_KEY environment variable.", + 401, + ); + } + + const queryString = buildQueryString(params); + const url = queryString ? `${BASE_URL}${endpoint}?${queryString}` : `${BASE_URL}${endpoint}`; + + const headers: Record = { + "X-MBX-APIKEY": API_KEY, + }; + + const response = await fetch(url, { method, headers }); + const rateLimitInfo = parseRateLimitInfo(response.headers); + + // Handle rate limiting (429) + if (response.status === 429) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); + throw new RateLimitError( + `Rate limit exceeded. Retry after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + // Handle IP ban (418) + if (response.status === 418) { + const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); + throw new IpBanError( + `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, + retryAfter, + rateLimitInfo, + ); + } + + if (!response.ok) { + const errorData = (await response.json().catch(() => ({ msg: response.statusText }))) as { + code?: number; + msg?: string; }; - - const response = await fetch(url, { method, headers }); - const rateLimitInfo = parseRateLimitInfo(response.headers); - - // Handle rate limiting (429) - if (response.status === 429) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10); - throw new RateLimitError( - `Rate limit exceeded. Retry after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - // Handle IP ban (418) - if (response.status === 418) { - const retryAfter = parseInt(response.headers.get("Retry-After") || "120", 10); - throw new IpBanError( - `IP temporarily banned. Ban lifted after ${retryAfter} seconds.`, - retryAfter, - rateLimitInfo - ); - } - - if (!response.ok) { - const errorData = await response.json().catch(() => ({ msg: response.statusText })); - throw new BinanceUsApiError( - errorData.code || response.status, - errorData.msg || response.statusText, - response.status, - rateLimitInfo - ); - } - - return response.json(); + throw new BinanceUsApiError( + errorData.code ?? response.status, + errorData.msg ?? response.statusText, + response.status, + rateLimitInfo, + ); + } + + return response.json(); } /** @@ -603,20 +614,20 @@ export async function makeMarketDataRequest( * @param recvWindow Optional receive window for signed requests (default 5000, max 60000) */ export async function binanceUsRequest( - method: "GET" | "POST" | "DELETE", - path: string, - params: Record = {}, - signed: boolean = false, - apiKeyRequired: boolean = false, - recvWindow?: number + method: "GET" | "POST" | "DELETE", + path: string, + params: Record = {}, + signed = false, + apiKeyRequired = false, + recvWindow?: number, ): Promise { - if (signed) { - return makeSignedRequest(method, path, params, recvWindow) as Promise; - } else if (apiKeyRequired) { - return makeMarketDataRequest("GET", path, params) as Promise; - } else { - return makePublicRequest("GET", path, params) as Promise; - } + if (signed) { + return makeSignedRequest(method, path, params, recvWindow) as Promise; + } else if (apiKeyRequired) { + return makeMarketDataRequest("GET", path, params) as Promise; + } else { + return makePublicRequest("GET", path, params) as Promise; + } } // ============================================================================ @@ -628,16 +639,41 @@ export const ORDER_BOOK_VALID_LIMITS = [5, 10, 20, 50, 100, 500, 1000, 5000] as /** Valid kline intervals */ export const KLINE_INTERVALS = [ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", ] as const; /** Valid rolling window sizes */ export const ROLLING_WINDOW_SIZES = [ - "1m", "2m", "3m", "4m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "7d" + "1m", + "2m", + "3m", + "4m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "7d", ] as const; /** Max results for trade endpoints */ diff --git a/src/config/client.ts b/src/config/client.ts index 51f03cd6..7aad5b90 100644 --- a/src/config/client.ts +++ b/src/config/client.ts @@ -1,16 +1,17 @@ -import { Algo } from '@binance/algo'; -import { Spot } from '@binance/connector-typescript'; - -const API_KEY = process.env.BINANCE_API_KEY; -const API_SECRET = process.env.BINANCE_API_SECRET; -const BASE_URL = 'https://api.binance.com'; - -export const spotClient = new Spot(API_KEY, API_SECRET, { baseURL: BASE_URL }); -export const algoClient = new Algo({ - configurationRestAPI: { - apiKey: API_KEY ?? '', - apiSecret: API_SECRET ?? '', - basePath: BASE_URL, - } -}); - +import { Algo } from "@binance/algo"; +import { Spot } from "@binance/connector-typescript"; + +import { URLS } from "./testnet.js"; + +const API_KEY = process.env.BINANCE_API_KEY; +const API_SECRET = process.env.BINANCE_API_SECRET; +const BASE_URL = URLS.SPOT_BASE_URL; + +export const spotClient = new Spot(API_KEY, API_SECRET, { baseURL: BASE_URL }); +export const algoClient = new Algo({ + configurationRestAPI: { + apiKey: API_KEY ?? "", + apiSecret: API_SECRET ?? "", + basePath: BASE_URL, + }, +}); diff --git a/src/config/testnet.ts b/src/config/testnet.ts new file mode 100644 index 00000000..ad53a0ba --- /dev/null +++ b/src/config/testnet.ts @@ -0,0 +1,92 @@ +// src/config/testnet.ts +// Binance Testnet configuration +// Reference: https://testnet.binance.vision + +import Logger from "../utils/logger.js"; + +export const IS_TESTNET = process.env.BINANCE_TESTNET === "true"; + +// Spot Testnet — only /api endpoints are supported (NOT /sapi) +const TESTNET_SPOT_BASE_URL = "https://testnet.binance.vision"; +const TESTNET_SPOT_WS_API_URL = "wss://ws-api.testnet.binance.vision/ws-api/v3"; +const TESTNET_SPOT_WS_STREAM_URL = "wss://stream.testnet.binance.vision"; + +// Futures Testnet — both USD-M (/fapi) and COIN-M (/dapi) share the same host +const TESTNET_FUTURES_BASE_URL = "https://testnet.binancefuture.com"; + +// Production URLs +const PROD_SPOT_BASE_URL = "https://api.binance.com"; +const PROD_SPOT_WS_API_URL = "wss://ws-api.binance.com/ws-api/v3"; +const PROD_SPOT_WS_STREAM_URL = "wss://stream.binance.com"; +const PROD_FUTURES_USD_BASE_URL = "https://fapi.binance.com"; +const PROD_FUTURES_COIN_BASE_URL = "https://dapi.binance.com"; +const PROD_OPTIONS_BASE_URL = "https://eapi.binance.com"; +const PROD_PAPI_BASE_URL = "https://papi.binance.com"; + +export const URLS = { + SPOT_BASE_URL: IS_TESTNET ? TESTNET_SPOT_BASE_URL : PROD_SPOT_BASE_URL, + SPOT_WS_API_URL: IS_TESTNET ? TESTNET_SPOT_WS_API_URL : PROD_SPOT_WS_API_URL, + SPOT_WS_STREAM_URL: IS_TESTNET ? TESTNET_SPOT_WS_STREAM_URL : PROD_SPOT_WS_STREAM_URL, + FUTURES_USD_BASE_URL: IS_TESTNET ? TESTNET_FUTURES_BASE_URL : PROD_FUTURES_USD_BASE_URL, + FUTURES_COIN_BASE_URL: IS_TESTNET ? TESTNET_FUTURES_BASE_URL : PROD_FUTURES_COIN_BASE_URL, + // No testnet for options / portfolio margin — always production + OPTIONS_BASE_URL: PROD_OPTIONS_BASE_URL, + PAPI_BASE_URL: PROD_PAPI_BASE_URL, +} as const; + +/** + * Endpoints using /sapi are NOT available on the Spot Test Network. + * This list of modules rely on /sapi and will not work in testnet mode. + */ +export const SAPI_ONLY_MODULES = [ + "Algo Trading", + "Auto-Invest", + "C2C (P2P)", + "Convert", + "Copy Trading", + "Crypto Loans", + "Dual Investment", + "Fiat", + "Gift Card", + "Margin", + "Mining", + "NFT", + "Pay", + "Portfolio Margin", + "Rebate", + "Simple Earn", + "Staking", + "Sub-Account", + "VIP Loan", + "Wallet", +] as const; + +/** + * Throws a descriptive error when a /sapi endpoint is called in testnet mode. + */ +export function assertNotTestnet(moduleName: string): void { + if (IS_TESTNET) { + throw new Error( + `[Testnet] ${moduleName} is not available on the Binance Spot Test Network. ` + + `Only /api endpoints are supported. See https://testnet.binance.vision`, + ); + } +} + +/** + * Log testnet status on startup. + */ +export function logTestnetStatus(): void { + if (IS_TESTNET) { + Logger.info("=== BINANCE TESTNET MODE ==="); + Logger.info(`Spot REST API: ${URLS.SPOT_BASE_URL}`); + Logger.info(`Spot WS API: ${URLS.SPOT_WS_API_URL}`); + Logger.info(`Spot WS Stream: ${URLS.SPOT_WS_STREAM_URL}`); + Logger.info(`Futures USD-M: ${URLS.FUTURES_USD_BASE_URL}`); + Logger.info(`Futures COIN-M: ${URLS.FUTURES_COIN_BASE_URL}`); + Logger.info(`Options: ${URLS.OPTIONS_BASE_URL} (no testnet available)`); + Logger.warn( + `The following modules use /sapi and are NOT available on testnet: ${SAPI_ONLY_MODULES.join(", ")}`, + ); + } +} diff --git a/src/config/types.ts b/src/config/types.ts index c5435357..3794bd01 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -58,22 +58,34 @@ export interface SymbolInfo { allowedSelfTradePreventionModes: string[]; } -export type SymbolStatus = "PRE_TRADING" | "TRADING" | "POST_TRADING" | "END_OF_DAY" | "HALT" | "AUCTION_MATCH" | "BREAK"; - -export type OrderType = "LIMIT" | "MARKET" | "STOP_LOSS_LIMIT" | "TAKE_PROFIT_LIMIT" | "LIMIT_MAKER"; +export type SymbolStatus = + | "PRE_TRADING" + | "TRADING" + | "POST_TRADING" + | "END_OF_DAY" + | "HALT" + | "AUCTION_MATCH" + | "BREAK"; + +export type OrderType = + | "LIMIT" + | "MARKET" + | "STOP_LOSS_LIMIT" + | "TAKE_PROFIT_LIMIT" + | "LIMIT_MAKER"; export type OrderSide = "BUY" | "SELL"; export type TimeInForce = "GTC" | "IOC" | "FOK"; -export type OrderStatus = - | "NEW" - | "PARTIALLY_FILLED" - | "FILLED" - | "CANCELED" - | "PENDING_CANCEL" - | "REJECTED" - | "EXPIRED" +export type OrderStatus = + | "NEW" + | "PARTIALLY_FILLED" + | "FILLED" + | "CANCELED" + | "PENDING_CANCEL" + | "REJECTED" + | "EXPIRED" | "EXPIRED_IN_MATCH"; export interface SymbolFilter { @@ -107,12 +119,12 @@ export interface Trade { * Aggregate Trade */ export interface AggregateTrade { - a: number; // Aggregate tradeId - p: string; // Price - q: string; // Quantity - f: number; // First tradeId - l: number; // Last tradeId - T: number; // Timestamp + a: number; // Aggregate tradeId + p: string; // Price + q: string; // Quantity + f: number; // First tradeId + l: number; // Last tradeId + T: number; // Timestamp m: boolean; // Was the buyer the maker? M: boolean; // Was the trade the best price match? } @@ -121,18 +133,18 @@ export interface AggregateTrade { * Candlestick/Kline */ export type Kline = [ - number, // Open time - string, // Open - string, // High - string, // Low - string, // Close - string, // Volume - number, // Close time - string, // Quote asset volume - number, // Number of trades - string, // Taker buy base asset volume - string, // Taker buy quote asset volume - string // Ignore + number, // Open time + string, // Open + string, // High + string, // Low + string, // Close + string, // Volume + number, // Close time + string, // Quote asset volume + number, // Number of trades + string, // Taker buy base asset volume + string, // Taker buy quote asset volume + string, // Ignore ]; /** @@ -508,4 +520,4 @@ export const ERROR_CODES = { ORDER_ARCHIVED: -2026, } as const; -export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES]; +export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; diff --git a/src/index.ts b/src/index.ts index e5f7751a..0a12fcee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,72 +1,87 @@ -#!/usr/bin/env node -import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" - -import { startSSEServer } from "./server/sse.js" -import { startStdioServer } from "./server/stdio.js" -import Logger from "./utils/logger.js" - -const args = process.argv.slice(2) - -// Transport mode flags -const sseMode = args.includes("--sse") || args.includes("-s") -// Default to stdio mode (for Claude Desktop) - -function printUsage() { - console.log(` -Binance MCP Server - -Usage: binance-mcp [options] - -Options: - --stdio, (default) Run in stdio mode (for Claude Desktop) - --sse, -s Run in SSE mode (HTTP) - -Environment Variables: - PORT Server port for SSE mode (default: 3002) - BINANCE_API_KEY Binance API key - BINANCE_API_SECRET Binance API secret - LOG_LEVEL Logging level (DEBUG, INFO, WARN, ERROR) - -Examples: - # Claude Desktop (stdio) - binance-mcp - - # SSE mode - binance-mcp --sse -`) -} - -async function main() { - if (args.includes("--help")) { - printUsage() - process.exit(0) - } - - let server: McpServer | undefined - - if (sseMode) { - Logger.info("Starting in SSE mode") - server = await startSSEServer() - } else { - // Default: stdio mode for Claude Desktop - server = await startStdioServer() - } - - if (!server) { - Logger.error("Failed to start server") - process.exit(1) - } - - const handleShutdown = async () => { - if ("close" in server && typeof server.close === "function") { - await server.close() - } - process.exit(0) - } - - // Handle process termination - process.on("SIGINT", handleShutdown) - process.on("SIGTERM", handleShutdown) -} - -main() +#!/usr/bin/env node +import "dotenv/config"; + +// If Binance API is IP-restricted, ensure requests bypass any proxy (HTTP_PROXY/HTTPS_PROXY) +// so Binance sees your real IP. See README "Troubleshooting: Invalid API-key, IP, or permissions". +if (!process.env.NO_PROXY?.includes("binance.com")) { + const binanceNoProxy = "api.binance.com,api1.binance.com,api2.binance.com,api3.binance.com"; + process.env.NO_PROXY = process.env.NO_PROXY + ? `${process.env.NO_PROXY},${binanceNoProxy}` + : binanceNoProxy; +} + +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { Server } from "http"; + +import { logTestnetStatus } from "./config/testnet.js"; +import { startSSEServer } from "./server/sse.js"; +import { startStdioServer } from "./server/stdio.js"; +import Logger from "./utils/logger.js"; + +const args = process.argv.slice(2); + +// Transport mode flags +const sseMode = args.includes("--sse") || args.includes("-s"); + +function printUsage() { + console.log(` +Binance MCP Server + +Usage: binance-mcp [options] + +Options: + --stdio, (default) Run in stdio mode (for Claude Desktop) + --sse, -s Run in SSE mode (HTTP) + +Environment Variables: + PORT Server port for SSE mode (default: 3002) + BINANCE_API_KEY Binance API key + BINANCE_API_SECRET Binance API secret + BINANCE_TESTNET Set to "true" to use Binance Spot Test Network + LOG_LEVEL Logging level (DEBUG, INFO, WARN, ERROR) + +Examples: + # Claude Desktop (stdio) + binance-mcp + + # SSE mode + binance-mcp --sse +`); +} + +async function main() { + if (args.includes("--help")) { + printUsage(); + process.exit(0); + } + + logTestnetStatus(); + + let handle: McpServer | Server | undefined; + + if (sseMode) { + Logger.info("Starting in SSE mode"); + handle = await startSSEServer(); + } else { + handle = await startStdioServer(); + } + + if (!handle) { + Logger.error("Failed to start server"); + process.exit(1); + } + + const server = handle; + + const handleShutdown = async () => { + if ("close" in server && typeof server.close === "function") { + await server.close(); + } + process.exit(0); + }; + + process.on("SIGINT", handleShutdown); + process.on("SIGTERM", handleShutdown); +} + +main(); diff --git a/src/init.ts b/src/init.ts index f8de7ba9..29398d4c 100644 --- a/src/init.ts +++ b/src/init.ts @@ -1,16 +1,18 @@ -import prompts, { PromptObject } from 'prompts'; -import figlet from 'figlet'; -import chalk from 'chalk'; -import path from 'path'; -import fs from 'fs-extra'; -import os from 'os'; -import { fileURLToPath } from 'url'; +import type { PromptObject } from "prompts"; +import os from "os"; +import path from "path"; +import { fileURLToPath } from "url"; + +import chalk from "chalk"; import dotenv from "dotenv"; +import figlet from "figlet"; +import fs from "fs-extra"; +import prompts from "prompts"; dotenv.config(); // Binance Gold Color -const yellow = chalk.hex('#F0B90B'); +const yellow = chalk.hex("#F0B90B"); // ESModule __dirname workaround const __filename = fileURLToPath(import.meta.url); @@ -18,144 +20,187 @@ const __dirname = path.dirname(__filename); // Cancel handler const onCancel = () => { - console.log(chalk.red('\n❌ Configuration cancelled by user (Ctrl+C or ESC). Exiting...')); - process.exit(0); + console.log(chalk.red("\n❌ Configuration cancelled by user (Ctrl+C or ESC). Exiting...")); + process.exit(0); }; // Show Banner const showBanner = () => { - const banner = figlet.textSync('Binance MCP ', { font: 'Big' }); - console.log(yellow(banner)); - console.log(yellow('🚀 Welcome to the Binance MCP Configurator\n')); + const banner = figlet.textSync("Binance MCP ", { font: "Big" }); + console.log(yellow(banner)); + console.log(yellow("🚀 Welcome to the Binance MCP Configurator\n")); }; // User Input Types interface UserInputs { - BINANCE_API_KEY: string; - BINANCE_API_SECRET: string; + BINANCE_API_KEY: string; + BINANCE_API_SECRET: string; + BINANCE_TESTNET: boolean; } // Ask for credentials const getInputs = async (): Promise => { - const questions: PromptObject[] = [ - { - type: 'password', - name: 'BINANCE_API_KEY', - message: '🔑Enter your BINANCE API KEY:', - validate: (val: string) => - val.trim() === '' ? 'BINANCE API KEY is required!' : true, - }, - { - type: 'password', - name: 'BINANCE_API_SECRET', - message: ' 🔐 Enter your BINANCE API SECRET:', - validate: (val: string) => - val.trim() === '' ? 'BINANCE API SECRET is required!' : true, - }, - ]; - - return await prompts(questions, { onCancel }) as UserInputs; + const questions: PromptObject[] = [ + { + type: "password", + name: "BINANCE_API_KEY", + message: "🔑Enter your BINANCE API KEY:", + validate: (val: string) => (val.trim() === "" ? "BINANCE API KEY is required!" : true), + }, + { + type: "password", + name: "BINANCE_API_SECRET", + message: " 🔐 Enter your BINANCE API SECRET:", + validate: (val: string) => (val.trim() === "" ? "BINANCE API SECRET is required!" : true), + }, + { + type: "confirm", + name: "BINANCE_TESTNET", + message: "🧪 Use Binance Spot Test Network? (testnet.binance.vision)", + initial: false, + }, + ]; + + return (await prompts(questions, { onCancel })) as UserInputs; }; // Generate .env file -const generateEnvFile = async (BINANCE_API_KEY: string, BINANCE_API_SECRET: string,): Promise => { - const envContent = ` +const generateEnvFile = async ( + BINANCE_API_KEY: string, + BINANCE_API_SECRET: string, + BINANCE_TESTNET: boolean, +): Promise => { + const envContent = ` BINANCE_API_KEY=${BINANCE_API_KEY} BINANCE_API_SECRET=${BINANCE_API_SECRET} +BINANCE_TESTNET=${BINANCE_TESTNET} `.trim(); - await fs.writeFile('.env', envContent); - console.log(yellow('✅ .env file generated.')); + await fs.writeFile(".env", envContent); + console.log(yellow("✅ .env file generated.")); }; // Generate config object -const generateConfig = async (BINANCE_API_KEY: string, BINANCE_API_SECRET: string,): Promise => { - const indexPath = path.resolve(__dirname, '..', 'build', 'index.js'); // one level up from cli/ - - return { - 'binance-mcp': { - command: 'node', - args: [indexPath], - env: { - BINANCE_API_KEY: BINANCE_API_KEY, - BINANCE_API_SECRET: BINANCE_API_SECRET, - }, - disabled: false, - autoApprove: [] - } - }; +const generateConfig = async ( + BINANCE_API_KEY: string, + BINANCE_API_SECRET: string, + BINANCE_TESTNET: boolean, +): Promise => { + const indexPath = path.resolve(__dirname, "..", "build", "index.js"); // one level up from cli/ + + const env: Record = { + BINANCE_API_KEY: BINANCE_API_KEY, + BINANCE_API_SECRET: BINANCE_API_SECRET, + }; + + if (BINANCE_TESTNET) { + env.BINANCE_TESTNET = "true"; + } + + return { + "binance-mcp": { + command: "bun", + args: ["run", indexPath], + env, + disabled: false, + autoApprove: [], + }, + }; }; // Configure Claude Desktop const configureClaude = async (config: object): Promise => { - const userHome = os.homedir(); - let claudePath; - const platform = os.platform(); - if (platform == "darwin") { - claudePath = path.join(userHome, 'Library/Application Support/Claude/claude_desktop_config.json'); - } else if (platform == "win32") { - claudePath = path.join(userHome, 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json'); - } else { - console.log(chalk.red('❌ Unsupported platform.')); - return false; - } - - if (!fs.existsSync(claudePath)) { - console.log(chalk.yellow('⚠️ Claude config file not found. Creating a new one with default configuration.')); - // Create a default configuration object - const defaultConfig = { - mcpServers: {} - }; - // Write the default configuration to the file - await fs.writeJSON(claudePath, defaultConfig, { spaces: 2 }); - } - - - const jsonData = fs.readFileSync(claudePath, 'utf8'); - const data = JSON.parse(jsonData); - - data.mcpServers = { - ...data.mcpServers, - ...config, + const userHome = os.homedir(); + let claudePath; + const platform = os.platform(); + if (platform == "darwin") { + claudePath = path.join( + userHome, + "Library/Application Support/Claude/claude_desktop_config.json", + ); + } else if (platform == "win32") { + claudePath = path.join(userHome, "AppData", "Roaming", "Claude", "claude_desktop_config.json"); + } else { + console.log(chalk.red("❌ Unsupported platform.")); + + return false; + } + + if (!fs.existsSync(claudePath)) { + console.log( + chalk.yellow( + "⚠️ Claude config file not found. Creating a new one with default configuration.", + ), + ); + // Create a default configuration object + const defaultConfig = { + mcpServers: {}, }; - - await fs.writeJSON(claudePath, data, { spaces: 2 }); - console.log(yellow('✅ Binance MCP configured for Claude Desktop. Please RESTART your Claude to enjoy it 🎉')); - return true; + // Write the default configuration to the file + await fs.writeJSON(claudePath, defaultConfig, { spaces: 2 }); + } + + const jsonData = fs.readFileSync(claudePath, "utf8"); + const data = JSON.parse(jsonData); + + data.mcpServers = { + ...data.mcpServers, + ...config, + }; + + await fs.writeJSON(claudePath, data, { spaces: 2 }); + console.log( + yellow( + "✅ Binance MCP configured for Claude Desktop. Please RESTART your Claude to enjoy it 🎉", + ), + ); + + return true; }; // Save fallback config file const saveFallbackConfig = async (config: object): Promise => { - await fs.writeJSON('config.json', config, { spaces: 2 }); - console.log(yellow('📁 Saved config.json in root project folder.')); + await fs.writeJSON("config.json", config, { spaces: 2 }); + console.log(yellow("📁 Saved config.json in root project folder.")); }; // Main logic const init = async () => { - showBanner(); - - const { BINANCE_API_KEY, BINANCE_API_SECRET } = await getInputs(); - - - await generateEnvFile(BINANCE_API_KEY, BINANCE_API_SECRET); - - const config = await generateConfig(BINANCE_API_KEY, BINANCE_API_SECRET); - - const { setupClaude } = await prompts({ - type: 'confirm', - name: 'setupClaude', - message: '🧠 Do you want to configure in Claude Desktop?', - initial: true - }, { onCancel }); - - if (setupClaude) { - const success = await configureClaude(config); - if (!success) { - await saveFallbackConfig(config); - } - } else { - await saveFallbackConfig(config); + showBanner(); + + const { BINANCE_API_KEY, BINANCE_API_SECRET, BINANCE_TESTNET } = await getInputs(); + + await generateEnvFile(BINANCE_API_KEY, BINANCE_API_SECRET, BINANCE_TESTNET); + + if (BINANCE_TESTNET) { + console.log( + yellow( + "🧪 Testnet mode enabled — API calls will go to testnet.binance.vision. " + + "Only /api endpoints (spot trading & market data) are available.", + ), + ); + } + + const config = await generateConfig(BINANCE_API_KEY, BINANCE_API_SECRET, BINANCE_TESTNET); + + const { setupClaude } = await prompts( + { + type: "confirm", + name: "setupClaude", + message: "🧠 Do you want to configure in Claude Desktop?", + initial: true, + }, + { onCancel }, + ); + + if (setupClaude) { + const success = await configureClaude(config); + if (!success) { + await saveFallbackConfig(config); } + } else { + await saveFallbackConfig(config); + } }; -init(); \ No newline at end of file +init(); diff --git a/src/modules/algo/future-algo/TwapNewTrade.ts b/src/modules/algo/future-algo/TwapNewTrade.ts index 2bae1220..89aef9f6 100644 --- a/src/modules/algo/future-algo/TwapNewTrade.ts +++ b/src/modules/algo/future-algo/TwapNewTrade.ts @@ -1,81 +1,95 @@ // src/tools/binance-algo/future-algo/TwapNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceTwapNewTrade(server: McpServer) { - server.tool( - "BinanceTimeWeightedAveragePriceNewOrder", + server.registerTool( + "BinanceTimeWeightedAveragePriceNewOrder", + { + description: "The Time-Weighted Average Price (TWAP) New Order API allows users to place a TWAP order on USDⓈ-M Contracts in Binance Futures. TWAP orders execute gradually over a specified duration to achieve a better average execution price while minimizing market impact.", - { - symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - positionSide: z - .enum(["BOTH", "LONG", "SHORT"]) - .optional() - .describe("Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. Must be sent in Hedge Mode."), - quantity: z - .number() - .positive() - .min(1000) - .max(1000000) - .describe("Quantity of base asset; Notional must be between 1,000 and 1,000,000 USDT"), - duration: z - .number() - .int() - .min(300) - .max(86400) - .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), - clientAlgoId: z.string().length(32).optional().describe("A unique 32-character ID among Algo orders"), - reduceOnly: z - .boolean() - .optional() - .describe("true or false. Default false; Cannot be sent in Hedge Mode or when opening a position"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.timeWeightedAveragePriceFutureAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - duration: params.duration, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe( + "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. Must be sent in Hedge Mode.", + ), + quantity: z + .number() + .positive() + .min(1000) + .max(1000000) + .describe("Quantity of base asset; Notional must be between 1,000 and 1,000,000 USDT"), + duration: z + .number() + .int() + .min(300) + .max(86400) + .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe("A unique 32-character ID among Algo orders"), + reduceOnly: z + .boolean() + .optional() + .describe( + "true or false. Default false; Cannot be sent in Hedge Mode or when opening a position", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.timeWeightedAveragePriceFutureAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + duration: params.duration, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place a TWAP order on: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place a TWAP order on: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/future-algo/VPNewTrade.ts b/src/modules/algo/future-algo/VPNewTrade.ts index 904623be..66056935 100644 --- a/src/modules/algo/future-algo/VPNewTrade.ts +++ b/src/modules/algo/future-algo/VPNewTrade.ts @@ -1,78 +1,90 @@ // src/tools/binance-algo/future-algo/VPNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceVPNewTrade(server: McpServer) { - server.tool( - "BinanceVolumeParticipationNewTrade", + server.registerTool( + "BinanceVolumeParticipationNewTrade", + { + description: "The Volume Participation (VP) New Order API allows users to place a VP order on USDⓈ-M Contracts in Binance Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - positionSide: z - .enum(["BOTH", "LONG", "SHORT"]) - .optional() - .describe( - "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. It must be sent in Hedge Mode." - ), - quantity: z - .number() - .positive() - .min(10000) - .max(1000000) - .describe("Quantity of base asset; Notional must be between 10,000 and 1,000,000 USDT"), - urgency: z.enum(["LOW", "MEDIUM", "HIGH"]).describe("Execution speed: LOW, MEDIUM, HIGH"), - clientAlgoId: z.string().length(32).optional().describe("A unique 32-character ID among Algo orders"), - reduceOnly: z - .boolean() - .optional() - .describe("true or false. Default false; Cannot be sent in Hedge Mode or when opening a position"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent"), - recvWindow: z.number().int().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.volumeParticipationFutureAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - urgency: params.urgency, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), - recvWindow: params.recvWindow - }); + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe( + "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. It must be sent in Hedge Mode.", + ), + quantity: z + .number() + .positive() + .min(10000) + .max(1000000) + .describe("Quantity of base asset; Notional must be between 10,000 and 1,000,000 USDT"), + urgency: z.enum(["LOW", "MEDIUM", "HIGH"]).describe("Execution speed: LOW, MEDIUM, HIGH"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe("A unique 32-character ID among Algo orders"), + reduceOnly: z + .boolean() + .optional() + .describe( + "true or false. Default false; Cannot be sent in Hedge Mode or when opening a position", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + recvWindow: z.number().int().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.volumeParticipationFutureAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + urgency: params.urgency, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + recvWindow: params.recvWindow, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `VP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `VP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place a VP order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place a VP order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/future-algo/cancelAlgoOrder.ts b/src/modules/algo/future-algo/cancelAlgoOrder.ts index cc80a4a3..4fc24f40 100644 --- a/src/modules/algo/future-algo/cancelAlgoOrder.ts +++ b/src/modules/algo/future-algo/cancelAlgoOrder.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/future-algo/cancelAlgoOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureCancelAlgoOrder(server: McpServer) { - server.tool( - "BinanceFutureCancelAlgoOrder", + server.registerTool( + "BinanceFutureCancelAlgoOrder", + { + description: "The Cancel Algo Order API allows users to cancel an active algorithmic order on USDⓈ-M Contracts in Binance Futures.", - { - algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.cancelAlgoOrderFutureAlgo({ - algoId: params.algoId, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.cancelAlgoOrderFutureAlgo({ + algoId: params.algoId, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to cancel Algo Order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to cancel Algo Order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/future-algo/currentAlgoOpenOrders.ts b/src/modules/algo/future-algo/currentAlgoOpenOrders.ts index 14a2de89..32dda635 100644 --- a/src/modules/algo/future-algo/currentAlgoOpenOrders.ts +++ b/src/modules/algo/future-algo/currentAlgoOpenOrders.ts @@ -1,43 +1,49 @@ // src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureCurrentAlgoOpenOrders(server: McpServer) { - server.tool( - "BinanceFutureCurrentAlgoOpenOrders", + server.registerTool( + "BinanceFutureCurrentAlgoOpenOrders", + { + description: "The Query Current Algo Open Orders API retrieves a list of currently active algorithmic orders for USDⓈ-M Contracts in Binance Futures.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersFutureAlgo({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersFutureAlgo({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Currently active algorithmic orders. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Currently active algorithmic orders. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Current Algo Open Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Current Algo Open Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/future-algo/historicalAlgoOrder.ts b/src/modules/algo/future-algo/historicalAlgoOrder.ts index bf3f942d..2e693e63 100644 --- a/src/modules/algo/future-algo/historicalAlgoOrder.ts +++ b/src/modules/algo/future-algo/historicalAlgoOrder.ts @@ -1,62 +1,76 @@ // src/tools/binance-algo/future-algo/historicalAlgoOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureHistoricalAlgoOrder(server: McpServer) { - server.tool( - "BinanceFutureHistoricalAlgoOrder", + server.registerTool( + "BinanceFutureHistoricalAlgoOrder", + { + description: "The Query Historical Algo Orders API retrieves a list of past algorithmic orders for USDⓈ-M Contracts in Binance Futures.", - { - symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryHistoricalAlgoOrdersFutureAlgo({ - ...(params.symbol !== undefined && { symbol: params.symbol }), - ...(params.side !== undefined && { side: params.side }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.page !== undefined && { page: params.page }), - ...(params.pageSize !== undefined && { pageSize: params.pageSize }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryHistoricalAlgoOrdersFutureAlgo({ + ...(params.symbol !== undefined && { symbol: params.symbol }), + ...(params.side !== undefined && { side: params.side }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.page !== undefined && { page: params.page }), + ...(params.pageSize !== undefined && { pageSize: params.pageSize }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Historical Algo Orders retrieves successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Historical Algo Orders retrieves successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Historical Algo Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Historical Algo Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/future-algo/index.ts b/src/modules/algo/future-algo/index.ts index 9dfdc703..503ac247 100644 --- a/src/modules/algo/future-algo/index.ts +++ b/src/modules/algo/future-algo/index.ts @@ -1,28 +1,29 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceVPNewTrade } from "./VPNewTrade.js"; -import { registerBinanceFutureHistoricalAlgoOrder } from "./historicalAlgoOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFutureCancelAlgoOrder } from "./cancelAlgoOrder.js"; import { registerBinanceFutureCurrentAlgoOpenOrders } from "./currentAlgoOpenOrders.js"; +import { registerBinanceFutureHistoricalAlgoOrder } from "./historicalAlgoOrder.js"; import { registerBinanceFutureSubOrders } from "./subOrders.js"; import { registerBinanceTwapNewTrade } from "./TwapNewTrade.js"; +import { registerBinanceVPNewTrade } from "./VPNewTrade.js"; export function registerBinanceAlgoFutureApiTools(server: McpServer) { - // Registers a new VP (Volume Participation) trade - registerBinanceVPNewTrade(server); + // Registers a new VP (Volume Participation) trade + registerBinanceVPNewTrade(server); - // Registers a new TWAP (Time-Weighted Average Price) trade - registerBinanceTwapNewTrade(server); + // Registers a new TWAP (Time-Weighted Average Price) trade + registerBinanceTwapNewTrade(server); - // Registers functionality to cancel an algorithmic order - registerBinanceFutureCancelAlgoOrder(server); + // Registers functionality to cancel an algorithmic order + registerBinanceFutureCancelAlgoOrder(server); - // Registers API to query sub-orders of an algorithmic order - registerBinanceFutureSubOrders(server); + // Registers API to query sub-orders of an algorithmic order + registerBinanceFutureSubOrders(server); - // Registers API to retrieve currently open algorithmic orders - registerBinanceFutureCurrentAlgoOpenOrders(server); + // Registers API to retrieve currently open algorithmic orders + registerBinanceFutureCurrentAlgoOpenOrders(server); - // Registers API to fetch historical algorithmic orders - registerBinanceFutureHistoricalAlgoOrder(server); + // Registers API to fetch historical algorithmic orders + registerBinanceFutureHistoricalAlgoOrder(server); } diff --git a/src/modules/algo/future-algo/subOrders.ts b/src/modules/algo/future-algo/subOrders.ts index cb334943..f36cbc6d 100644 --- a/src/modules/algo/future-algo/subOrders.ts +++ b/src/modules/algo/future-algo/subOrders.ts @@ -1,58 +1,64 @@ // src/tools/binance-algo/future-algo/subOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureSubOrders(server: McpServer) { - server.tool( - "BinanceFutureSubOrders", + server.registerTool( + "BinanceFutureSubOrders", + { + description: "The Sub Orders API retrieves sub-orders associated with a specified algoId for USDⓈ-M Contracts in Binance Futures.", - { - algoId: z.number().int().describe("Algo order ID"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.querySubOrdersFutureAlgo({ - algoId: params.algoId, - page: params.page, - pageSize: params.pageSize, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.querySubOrdersFutureAlgo({ + algoId: params.algoId, + page: params.page, + pageSize: params.pageSize, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub Orders retrieved successfully for id ${ + params.algoId + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Sub Orders retrieved successfully for id ${ - params.algoId - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve retrieve sub-orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve retrieve sub-orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/index.ts b/src/modules/algo/index.ts index 864916a6..feaa771c 100644 --- a/src/modules/algo/index.ts +++ b/src/modules/algo/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-spot/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceAlgoFutureApiTools } from "./future-algo/index.js"; import { registerBinanceAlgoSpotApiTools } from "./spot-algo/index.js"; export function registerBinanceAlgoTools(server: McpServer) { - // Algo API tools - registerBinanceAlgoFutureApiTools(server); - registerBinanceAlgoSpotApiTools(server); + // Algo API tools + registerBinanceAlgoFutureApiTools(server); + registerBinanceAlgoSpotApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/algo/spot-algo/cancelOpenTWAPOrder.ts b/src/modules/algo/spot-algo/cancelOpenTWAPOrder.ts index d69c2904..e2068e02 100644 --- a/src/modules/algo/spot-algo/cancelOpenTWAPOrder.ts +++ b/src/modules/algo/spot-algo/cancelOpenTWAPOrder.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotCancelOpenTWAPOrder(server: McpServer) { - server.tool( - "BinanceSpotCancelOpenTWAPOrder", + server.registerTool( + "BinanceSpotCancelOpenTWAPOrder", + { + description: "The Cancel Algo Order API allows users to cancel an open TWAP algorithmic order for spot trading on Binance.", - { - algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.cancelAlgoOrderSpotAlgo({ - algoId: params.algoId, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.cancelAlgoOrderSpotAlgo({ + algoId: params.algoId, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Cancel Algo Order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Cancel Algo Order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/spot-algo/currentAlgoOpenOrders.ts b/src/modules/algo/spot-algo/currentAlgoOpenOrders.ts index c47bc2cc..ad57c20a 100644 --- a/src/modules/algo/spot-algo/currentAlgoOpenOrders.ts +++ b/src/modules/algo/spot-algo/currentAlgoOpenOrders.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotCurrentAlgoOpenOrders(server: McpServer) { - server.tool( - "BinanceSpotCurrentAlgoOpenOrders", + server.registerTool( + "BinanceSpotCurrentAlgoOpenOrders", + { + description: "This API retrieves all open SPOT TWAP (Time-Weighted Average Price) orders on Binance.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersSpotAlgo({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersSpotAlgo({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieve all open SPOT TWAP (Time-Weighted Average Price) orders. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieve all open SPOT TWAP (Time-Weighted Average Price) orders. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieves all open SPOT TWAP: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieves all open SPOT TWAP: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/spot-algo/historicalAlgoOrders.ts b/src/modules/algo/spot-algo/historicalAlgoOrders.ts index aa95a22e..9c26464b 100644 --- a/src/modules/algo/spot-algo/historicalAlgoOrders.ts +++ b/src/modules/algo/spot-algo/historicalAlgoOrders.ts @@ -1,64 +1,78 @@ // src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotHistoricalAlgoOrders(server: McpServer) { - server.tool( - "BinanceSpotHistoricalAlgoOrders", + server.registerTool( + "BinanceSpotHistoricalAlgoOrders", + { + description: "This API retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance.", - { - symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryHistoricalAlgoOrdersSpotAlgo({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.side && { side: params.side }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryHistoricalAlgoOrdersSpotAlgo({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.side && { side: params.side }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve all historical SPOT TWAP: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve all historical SPOT TWAP: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/spot-algo/index.ts b/src/modules/algo/spot-algo/index.ts index d43c1f94..366e4f7d 100644 --- a/src/modules/algo/spot-algo/index.ts +++ b/src/modules/algo/spot-algo/index.ts @@ -1,24 +1,25 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSpotTwapNewTrade } from "./spotTWAPOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSpotCancelOpenTWAPOrder } from "./cancelOpenTWAPOrder.js"; -import { registerBinanceSpotSubOrders } from "./subOrders.js"; import { registerBinanceSpotCurrentAlgoOpenOrders } from "./currentAlgoOpenOrders.js"; import { registerBinanceSpotHistoricalAlgoOrders } from "./historicalAlgoOrders.js"; +import { registerBinanceSpotTwapNewTrade } from "./spotTWAPOrder.js"; +import { registerBinanceSpotSubOrders } from "./subOrders.js"; export function registerBinanceAlgoSpotApiTools(server: McpServer) { - // Register the TWAP (Time-Weighted Average Price) tool for placing new spot algo orders - registerBinanceSpotTwapNewTrade(server); + // Register the TWAP (Time-Weighted Average Price) tool for placing new spot algo orders + registerBinanceSpotTwapNewTrade(server); - // Register the tool for canceling open TWAP spot algo orders - registerBinanceSpotCancelOpenTWAPOrder(server); + // Register the tool for canceling open TWAP spot algo orders + registerBinanceSpotCancelOpenTWAPOrder(server); - // Register the tool to handle sub-orders created under a parent algo order - registerBinanceSpotSubOrders(server); + // Register the tool to handle sub-orders created under a parent algo order + registerBinanceSpotSubOrders(server); - // Register the tool to fetch currently open algo orders for spot trading - registerBinanceSpotCurrentAlgoOpenOrders(server); + // Register the tool to fetch currently open algo orders for spot trading + registerBinanceSpotCurrentAlgoOpenOrders(server); - // Register the tool to fetch historical algo orders for spot trading - registerBinanceSpotHistoricalAlgoOrders(server); + // Register the tool to fetch historical algo orders for spot trading + registerBinanceSpotHistoricalAlgoOrders(server); } diff --git a/src/modules/algo/spot-algo/spotTWAPOrder.ts b/src/modules/algo/spot-algo/spotTWAPOrder.ts index 60b6f055..0d69adf7 100644 --- a/src/modules/algo/spot-algo/spotTWAPOrder.ts +++ b/src/modules/algo/spot-algo/spotTWAPOrder.ts @@ -1,73 +1,81 @@ // src/tools/binance-algo/spot-algo/spotTwapNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { algoClient } from "../../../config/binanceClient.js"; export function registerBinanceSpotTwapNewTrade(server: McpServer) { - server.tool( - "BinanceSpotTimeWeightedAveragePriceNewOrder", + server.registerTool( + "BinanceSpotTimeWeightedAveragePriceNewOrder", + { + description: "The TWAP (Time-Weighted Average Price) New Order API allows users to place TWAP algorithmic orders for USDⓈ-M Futures on Binance.", - { - symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - quantity: z - .number() - .positive() - .describe( - "Quantity of base asset; Maximum notional per order is 200k, 2mm, or 10mm, depending on the symbol" - ), - duration: z - .number() - .int() - .min(300) - .max(86400) - .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), - clientAlgoId: z - .string() - .length(32) - .optional() - .describe("A unique 32-character ID among Algo orders. If not sent, a default value will be assigned"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent") - }, - async (params) => { - try { - const response = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - duration: params.duration, - ...(params.clientAlgoId !== undefined && { clientAlgoId: params.clientAlgoId }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }) - }); + inputSchema: { + symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + quantity: z + .number() + .positive() + .describe( + "Quantity of base asset; Maximum notional per order is 200k, 2mm, or 10mm, depending on the symbol", + ), + duration: z + .number() + .int() + .min(300) + .max(86400) + .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe( + "A unique 32-character ID among Algo orders. If not sent, a default value will be assigned", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + duration: params.duration, + ...(params.clientAlgoId !== undefined && { clientAlgoId: params.clientAlgoId }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place TWAP algorithmic orders for USDⓈ-M Futures on Binance: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place TWAP algorithmic orders for USDⓈ-M Futures on Binance: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/algo/spot-algo/subOrders.ts b/src/modules/algo/spot-algo/subOrders.ts index 6836d7b4..ba459141 100644 --- a/src/modules/algo/spot-algo/subOrders.ts +++ b/src/modules/algo/spot-algo/subOrders.ts @@ -1,58 +1,64 @@ // src/tools/binance-algo/spot-algo/subOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { algoClient } from "../../../config/binanceClient.js"; export function registerBinanceSpotSubOrders(server: McpServer) { - server.tool( - "BinanceSpotSubOrders", + server.registerTool( + "BinanceSpotSubOrders", + { + description: "The Query Sub Orders API retrieves details of sub-orders associated with a specific algorithmic (Algo) order for spot trading on Binance.", - { - algoId: z.number().int().describe("Algo order ID"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.querySubOrdersSpotAlgo({ - algoId: params.algoId, - ...(params.page !== undefined && { page: params.page }), - ...(params.pageSize !== undefined && { pageSize: params.pageSize }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.querySubOrdersSpotAlgo({ + algoId: params.algoId, + ...(params.page !== undefined && { page: params.page }), + ...(params.pageSize !== undefined && { pageSize: params.pageSize }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub Orders retrieved successfully for id${params.algoId}. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Sub Orders retrieved successfully for id${params.algoId}. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Sub Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Sub Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/changePlanStatus.ts b/src/modules/auto-invest/changePlanStatus.ts index 182a20e8..bf15658d 100644 --- a/src/modules/auto-invest/changePlanStatus.ts +++ b/src/modules/auto-invest/changePlanStatus.ts @@ -5,47 +5,58 @@ * @license Apache-2.0 */ // src/modules/auto-invest/changePlanStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestChangePlanStatus(server: McpServer) { - server.tool( - "BinanceAutoInvestChangePlanStatus", - "Change the status of an auto-invest plan (pause or resume).", - { - planId: z.number().int().describe("Plan ID to modify"), - status: z.enum(["ONGOING", "PAUSED"]).describe("New status (ONGOING to resume, PAUSED to pause)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.planEditStatus({ - planId: params.planId, - status: params.status, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const statusText = params.status === "ONGOING" ? "resumed" : "paused"; - - return { - content: [{ - type: "text", - text: `✅ Auto-invest plan ${statusText}!\n\nPlan ID: ${params.planId}\nNew Status: ${params.status}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to change auto-invest plan status: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestChangePlanStatus", + { + description: "Change the status of an auto-invest plan (pause or resume).", + inputSchema: { + planId: z.number().int().describe("Plan ID to modify"), + status: z + .enum(["ONGOING", "PAUSED"]) + .describe("New status (ONGOING to resume, PAUSED to pause)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.changePlanStatus({ + planId: params.planId, + status: params.status, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const statusText = params.status === "ONGOING" ? "resumed" : "paused"; + + return { + content: [ + { + type: "text", + text: `✅ Auto-invest plan ${statusText}!\n\nPlan ID: ${params.planId}\nNew Status: ${params.status}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to change auto-invest plan status: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/createPlan.ts b/src/modules/auto-invest/createPlan.ts index 6f33f73e..9765cd07 100644 --- a/src/modules/auto-invest/createPlan.ts +++ b/src/modules/auto-invest/createPlan.ts @@ -5,65 +5,87 @@ * @license Apache-2.0 */ // src/modules/auto-invest/createPlan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestCreatePlan(server: McpServer) { - server.tool( - "BinanceAutoInvestCreatePlan", + server.registerTool( + "BinanceAutoInvestCreatePlan", + { + description: "Create an auto-invest plan for dollar-cost averaging. Automatically purchases crypto at regular intervals.", - { - sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).describe("Plan type"), - subscriptionAmount: z.string().describe("Amount per subscription"), - subscriptionCycle: z.enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) - .describe("Subscription frequency"), - subscriptionStartDay: z.number().int().optional() - .describe("Start day (1-31 for MONTHLY, 1-7 for WEEKLY)"), - subscriptionStartTime: z.number().int().min(0).max(23).describe("Start hour (0-23)"), - sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), - flexibleAllowedToUse: z.boolean().optional() - .describe("Allow using flexible savings balance"), - details: z.array(z.object({ - targetAsset: z.string().describe("Target asset to purchase"), - percentage: z.number().describe("Percentage allocation (0-100)") - })).describe("Target assets and allocation percentages"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.planAdd({ - sourceType: params.sourceType, - planType: params.planType, - subscriptionAmount: params.subscriptionAmount, - subscriptionCycle: params.subscriptionCycle, - subscriptionStartTime: params.subscriptionStartTime, - sourceAsset: params.sourceAsset, - details: JSON.stringify(params.details), - ...(params.subscriptionStartDay && { subscriptionStartDay: params.subscriptionStartDay }), - ...(params.flexibleAllowedToUse !== undefined && { flexibleAllowedToUse: params.flexibleAllowedToUse }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Auto-invest plan created!\n\nPlan ID: ${data.planId}\nNext Execution: ${data.nextExecutionDateTime || 'Scheduled'}\n\nYour recurring investment plan is now active.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to create auto-invest plan: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), + planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).describe("Plan type"), + subscriptionAmount: z.string().describe("Amount per subscription"), + subscriptionCycle: z + .enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) + .describe("Subscription frequency"), + subscriptionStartDay: z + .number() + .int() + .optional() + .describe("Start day (1-31 for MONTHLY, 1-7 for WEEKLY)"), + subscriptionStartTime: z.number().int().min(0).max(23).describe("Start hour (0-23)"), + sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Allow using flexible savings balance"), + details: z + .array( + z.object({ + targetAsset: z.string().describe("Target asset to purchase"), + percentage: z.number().describe("Percentage allocation (0-100)"), + }), + ) + .describe("Target assets and allocation percentages"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.investmentPlanCreation({ + sourceType: params.sourceType, + planType: params.planType, + subscriptionAmount: params.subscriptionAmount, + subscriptionCycle: params.subscriptionCycle, + subscriptionStartTime: params.subscriptionStartTime, + sourceAsset: params.sourceAsset, + details: JSON.stringify(params.details), + ...(params.subscriptionStartDay && { subscriptionStartDay: params.subscriptionStartDay }), + ...(params.flexibleAllowedToUse !== undefined && { + flexibleAllowedToUse: params.flexibleAllowedToUse, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Auto-invest plan created!\n\nPlan ID: ${data.planId}\nNext Execution: ${data.nextExecutionDateTime || "Scheduled"}\n\nYour recurring investment plan is now active.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to create auto-invest plan: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/editPlan.ts b/src/modules/auto-invest/editPlan.ts index da0ae5f5..0b4f98d6 100644 --- a/src/modules/auto-invest/editPlan.ts +++ b/src/modules/auto-invest/editPlan.ts @@ -5,63 +5,85 @@ * @license Apache-2.0 */ // src/modules/auto-invest/editPlan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestEditPlan(server: McpServer) { - server.tool( - "BinanceAutoInvestEditPlan", + server.registerTool( + "BinanceAutoInvestEditPlan", + { + description: "Edit an existing auto-invest plan. Modify subscription amount, cycle, or target allocations.", - { - planId: z.number().int().describe("Plan ID to edit"), - subscriptionAmount: z.string().describe("New amount per subscription"), - subscriptionCycle: z.enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) - .describe("New subscription frequency"), - subscriptionStartDay: z.number().int().optional() - .describe("New start day (1-31 for MONTHLY, 1-7 for WEEKLY)"), - subscriptionStartTime: z.number().int().min(0).max(23).describe("New start hour (0-23)"), - sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), - flexibleAllowedToUse: z.boolean().optional() - .describe("Allow using flexible savings balance"), - details: z.array(z.object({ - targetAsset: z.string().describe("Target asset to purchase"), - percentage: z.number().describe("Percentage allocation (0-100)") - })).describe("New target assets and allocation percentages"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.planEdit({ - planId: params.planId, - subscriptionAmount: params.subscriptionAmount, - subscriptionCycle: params.subscriptionCycle, - subscriptionStartTime: params.subscriptionStartTime, - sourceAsset: params.sourceAsset, - details: JSON.stringify(params.details), - ...(params.subscriptionStartDay && { subscriptionStartDay: params.subscriptionStartDay }), - ...(params.flexibleAllowedToUse !== undefined && { flexibleAllowedToUse: params.flexibleAllowedToUse }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Auto-invest plan updated!\n\nPlan ID: ${params.planId}\nNext Execution: ${data.nextExecutionDateTime || 'Scheduled'}\n\nYour plan has been modified.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to edit auto-invest plan: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + planId: z.number().int().describe("Plan ID to edit"), + subscriptionAmount: z.string().describe("New amount per subscription"), + subscriptionCycle: z + .enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) + .describe("New subscription frequency"), + subscriptionStartDay: z + .number() + .int() + .optional() + .describe("New start day (1-31 for MONTHLY, 1-7 for WEEKLY)"), + subscriptionStartTime: z.number().int().min(0).max(23).describe("New start hour (0-23)"), + sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Allow using flexible savings balance"), + details: z + .array( + z.object({ + targetAsset: z.string().describe("Target asset to purchase"), + percentage: z.number().describe("Percentage allocation (0-100)"), + }), + ) + .describe("New target assets and allocation percentages"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.investmentPlanAdjustment({ + planId: params.planId, + subscriptionAmount: params.subscriptionAmount, + subscriptionCycle: params.subscriptionCycle, + subscriptionStartTime: params.subscriptionStartTime, + sourceAsset: params.sourceAsset, + details: JSON.stringify(params.details), + ...(params.subscriptionStartDay && { subscriptionStartDay: params.subscriptionStartDay }), + ...(params.flexibleAllowedToUse !== undefined && { + flexibleAllowedToUse: params.flexibleAllowedToUse, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Auto-invest plan updated!\n\nPlan ID: ${params.planId}\nNext Execution: ${data.nextExecutionDateTime || "Scheduled"}\n\nYour plan has been modified.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to edit auto-invest plan: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getHistoryList.ts b/src/modules/auto-invest/getHistoryList.ts index bd4574c2..c7eae4fe 100644 --- a/src/modules/auto-invest/getHistoryList.ts +++ b/src/modules/auto-invest/getHistoryList.ts @@ -5,78 +5,98 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getHistoryList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetHistoryList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetHistoryList", - "Get auto-invest transaction history. Shows all past recurring purchases.", - { - planId: z.number().int().optional().describe("Filter by plan ID"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - targetAsset: z.string().optional().describe("Filter by target asset"), - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]).optional().describe("Plan type filter"), - size: z.number().int().min(1).max(100).optional().describe("Number of results (default 10, max 100)"), - current: z.number().int().min(1).optional().describe("Page number (default 1)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.historyList({ - ...(params.planId && { planId: params.planId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.targetAsset && { targetAsset: params.targetAsset }), - ...(params.planType && { planType: params.planType }), - ...(params.size && { size: params.size }), - ...(params.current && { current: params.current }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Transaction History\n\n`; - - const history = data.list || data.data || data; - - if (Array.isArray(history) && history.length > 0) { - result += `Total transactions: ${data.total || history.length}\n\n`; - history.slice(0, 20).forEach((tx: any, index: number) => { - result += `**${index + 1}. Transaction ID: ${tx.id || tx.transactionId}**\n`; - result += ` Plan ID: ${tx.planId}\n`; - result += ` Target Asset: ${tx.targetAsset}\n`; - result += ` Source Asset: ${tx.sourceAsset}\n`; - result += ` Source Amount: ${tx.sourceAmount || tx.sourceAssetAmount}\n`; - result += ` Target Amount: ${tx.targetAmount || tx.targetAssetAmount}\n`; - result += ` Status: ${tx.status}\n`; - result += ` Time: ${tx.transactionDateTime || new Date(tx.time).toISOString()}\n\n`; - }); - if (history.length > 20) { - result += `... and ${history.length - 20} more transactions`; - } - } else { - result += `No transaction history found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest history: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceAutoInvestGetHistoryList", + { + description: "Get auto-invest transaction history. Shows all past recurring purchases.", + inputSchema: { + planId: z.number().int().optional().describe("Filter by plan ID"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + targetAsset: z.string().optional().describe("Filter by target asset"), + planType: z + .enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]) + .optional() + .describe("Plan type filter"), + size: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of results (default 10, max 100)"), + current: z.number().int().min(1).optional().describe("Page number (default 1)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await ( + autoInvestClient as any + ).restAPI.querySubscriptionTransactionHistory({ + ...(params.planId && { planId: params.planId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.targetAsset && { targetAsset: params.targetAsset }), + ...(params.planType && { planType: params.planType }), + ...(params.size && { size: params.size }), + ...(params.current && { current: params.current }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Transaction History\n\n`; + + const history = data.list || data.data || data; + + if (Array.isArray(history) && history.length > 0) { + result += `Total transactions: ${data.total || history.length}\n\n`; + history.slice(0, 20).forEach((tx: any, index: number) => { + result += `**${index + 1}. Transaction ID: ${tx.id || tx.transactionId}**\n`; + result += ` Plan ID: ${tx.planId}\n`; + result += ` Target Asset: ${tx.targetAsset}\n`; + result += ` Source Asset: ${tx.sourceAsset}\n`; + result += ` Source Amount: ${tx.sourceAmount || tx.sourceAssetAmount}\n`; + result += ` Target Amount: ${tx.targetAmount || tx.targetAssetAmount}\n`; + result += ` Status: ${tx.status}\n`; + result += ` Time: ${tx.transactionDateTime || new Date(tx.time).toISOString()}\n\n`; + }); + if (history.length > 20) { + result += `... and ${history.length - 20} more transactions`; + } + } else { + result += `No transaction history found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getIndexInfo.ts b/src/modules/auto-invest/getIndexInfo.ts index ccec9e76..7e7e6847 100644 --- a/src/modules/auto-invest/getIndexInfo.ts +++ b/src/modules/auto-invest/getIndexInfo.ts @@ -5,63 +5,73 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getIndexInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetIndexInfo(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexInfo", + server.registerTool( + "BinanceAutoInvestGetIndexInfo", + { + description: "Get auto-invest index information. Index plans allow investing in a basket of cryptocurrencies.", - { - indexId: z.number().int().optional().describe("Specific index ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.indexInfo({ - ...(params.indexId && { indexId: params.indexId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Index Information\n\n`; - - if (data.indexId) { - result += `**Index ID: ${data.indexId}**\n`; - result += `Status: ${data.status}\n\n`; - if (data.assetAllocation && Array.isArray(data.assetAllocation)) { - result += `**Asset Allocation**\n`; - data.assetAllocation.forEach((asset: any) => { - result += `- ${asset.targetAsset}: ${asset.allocation}%\n`; - }); - } - } else if (Array.isArray(data)) { - data.forEach((index: any) => { - result += `**Index ID: ${index.indexId}**\n`; - result += `Status: ${index.status}\n\n`; - }); - } else { - result += `Index Info: ${JSON.stringify(data)}`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest index info: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + indexId: z.number().int().optional().describe("Specific index ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.queryIndexDetails({ + ...(params.indexId && { indexId: params.indexId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Index Information\n\n`; + + if (data.indexId) { + result += `**Index ID: ${data.indexId}**\n`; + result += `Status: ${data.status}\n\n`; + if (data.assetAllocation && Array.isArray(data.assetAllocation)) { + result += `**Asset Allocation**\n`; + data.assetAllocation.forEach((asset: any) => { + result += `- ${asset.targetAsset}: ${asset.allocation}%\n`; + }); + } + } else if (Array.isArray(data)) { + data.forEach((index: any) => { + result += `**Index ID: ${index.indexId}**\n`; + result += `Status: ${index.status}\n\n`; + }); + } else { + result += `Index Info: ${JSON.stringify(data)}`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest index info: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getIndexLinkedPlanPositionDetails.ts b/src/modules/auto-invest/getIndexLinkedPlanPositionDetails.ts index 1c8457c9..f6f08e54 100644 --- a/src/modules/auto-invest/getIndexLinkedPlanPositionDetails.ts +++ b/src/modules/auto-invest/getIndexLinkedPlanPositionDetails.ts @@ -5,67 +5,79 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getIndexLinkedPlanPositionDetails.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetIndexLinkedPlanPositionDetails(server: McpServer) { - server.tool( - "BinanceAutoInvestGetPlanDetails", + server.registerTool( + "BinanceAutoInvestGetPlanDetails", + { + description: "Get detailed information about a specific auto-invest plan including position details.", - { - planId: z.number().int().describe("Plan ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.planId({ - planId: params.planId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Plan Details\n\n`; - result += `Plan ID: ${params.planId}\n\n`; - - if (data) { - result += `**Plan Configuration**\n`; - result += `Type: ${data.planType || 'N/A'}\n`; - result += `Status: ${data.status || 'N/A'}\n`; - result += `Source Asset: ${data.sourceAsset || 'N/A'}\n`; - result += `Subscription Amount: ${data.subscriptionAmount || 'N/A'}\n`; - result += `Cycle: ${data.subscriptionCycle || 'N/A'}\n`; - result += `Next Execution: ${data.nextExecutionDateTime || 'N/A'}\n\n`; - - if (data.details && Array.isArray(data.details)) { - result += `**Position Details**\n`; - data.details.forEach((detail: any) => { - result += `**${detail.targetAsset}** (${detail.percentage}%)\n`; - result += ` Purchased Amount: ${detail.purchasedAmount || '0'}\n`; - result += ` Average Price: ${detail.avgPrice || 'N/A'}\n`; - result += ` Current Value: ${detail.currentValue || 'N/A'}\n`; - result += ` PnL: ${detail.pnl || 'N/A'}\n\n`; - }); - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest plan details: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + planId: z.number().int().describe("Plan ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await ( + autoInvestClient as any + ).restAPI.queryIndexLinkedPlanPositionDetails({ + planId: params.planId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Plan Details\n\n`; + result += `Plan ID: ${params.planId}\n\n`; + + if (data) { + result += `**Plan Configuration**\n`; + result += `Type: ${data.planType || "N/A"}\n`; + result += `Status: ${data.status || "N/A"}\n`; + result += `Source Asset: ${data.sourceAsset || "N/A"}\n`; + result += `Subscription Amount: ${data.subscriptionAmount || "N/A"}\n`; + result += `Cycle: ${data.subscriptionCycle || "N/A"}\n`; + result += `Next Execution: ${data.nextExecutionDateTime || "N/A"}\n\n`; + + if (data.details && Array.isArray(data.details)) { + result += `**Position Details**\n`; + data.details.forEach((detail: any) => { + result += `**${detail.targetAsset}** (${detail.percentage}%)\n`; + result += ` Purchased Amount: ${detail.purchasedAmount || "0"}\n`; + result += ` Average Price: ${detail.avgPrice || "N/A"}\n`; + result += ` Current Value: ${detail.currentValue || "N/A"}\n`; + result += ` PnL: ${detail.pnl || "N/A"}\n\n`; + }); + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest plan details: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getIndexUserSummary.ts b/src/modules/auto-invest/getIndexUserSummary.ts index c376857c..068dbe54 100644 --- a/src/modules/auto-invest/getIndexUserSummary.ts +++ b/src/modules/auto-invest/getIndexUserSummary.ts @@ -5,53 +5,62 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getIndexUserSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetIndexUserSummary(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexUserSummary", - "Get user's auto-invest index subscription summary.", - { - indexId: z.number().int().describe("Index ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.indexUserSummary({ - indexId: params.indexId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Index User Summary\n\n`; - result += `Index ID: ${params.indexId}\n\n`; - - if (data) { - result += `Total Invested: ${data.totalInvestedInUSD || data.totalInvested || 'N/A'}\n`; - result += `Current Value: ${data.currentInvestedInUSD || data.currentValue || 'N/A'}\n`; - result += `PnL: ${data.pnlInUSD || data.pnl || 'N/A'}\n`; - result += `ROI: ${data.roi || 'N/A'}%\n`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest index user summary: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceAutoInvestGetIndexUserSummary", + { + description: "Get user's auto-invest index subscription summary.", + inputSchema: { + indexId: z.number().int().describe("Index ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.queryIndexDetails({ + indexId: params.indexId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Index User Summary\n\n`; + result += `Index ID: ${params.indexId}\n\n`; + + if (data) { + result += `Total Invested: ${data.totalInvestedInUSD || data.totalInvested || "N/A"}\n`; + result += `Current Value: ${data.currentInvestedInUSD || data.currentValue || "N/A"}\n`; + result += `PnL: ${data.pnlInUSD || data.pnl || "N/A"}\n`; + result += `ROI: ${data.roi || "N/A"}%\n`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest index user summary: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getPlanList.ts b/src/modules/auto-invest/getPlanList.ts index d25250f4..08f89568 100644 --- a/src/modules/auto-invest/getPlanList.ts +++ b/src/modules/auto-invest/getPlanList.ts @@ -5,70 +5,82 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getPlanList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetPlanList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetPlanList", - "Get list of user's auto-invest plans. Shows all recurring investment plans.", - { - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]).optional().describe("Plan type filter"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.planList({ - ...(params.planType && { planType: params.planType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Plans\n\n`; - - const plans = data.planList || data.plans || data; - - if (Array.isArray(plans) && plans.length > 0) { - result += `Total plans: ${plans.length}\n\n`; - plans.forEach((plan: any, index: number) => { - result += `**${index + 1}. Plan ID: ${plan.planId}**\n`; - result += ` Type: ${plan.planType}\n`; - result += ` Status: ${plan.status}\n`; - result += ` Source Asset: ${plan.sourceAsset}\n`; - result += ` Subscription Amount: ${plan.subscriptionAmount}\n`; - result += ` Cycle: ${plan.subscriptionCycle}\n`; - result += ` Next Execution: ${plan.nextExecutionDateTime || 'N/A'}\n\n`; - - if (plan.details && Array.isArray(plan.details)) { - result += ` **Target Assets:**\n`; - plan.details.forEach((detail: any) => { - result += ` - ${detail.targetAsset}: ${detail.percentage}%\n`; - }); - result += '\n'; - } - }); - } else { - result += `No auto-invest plans found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest plans: ${errorMessage}` - }], - isError: true - }; + server.registerTool( + "BinanceAutoInvestGetPlanList", + { + description: "Get list of user's auto-invest plans. Shows all recurring investment plans.", + inputSchema: { + planType: z + .enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]) + .optional() + .describe("Plan type filter"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getListOfPlans({ + ...(params.planType && { planType: params.planType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Plans\n\n`; + + const plans = data.planList || data.plans || data; + + if (Array.isArray(plans) && plans.length > 0) { + result += `Total plans: ${plans.length}\n\n`; + plans.forEach((plan: any, index: number) => { + result += `**${index + 1}. Plan ID: ${plan.planId}**\n`; + result += ` Type: ${plan.planType}\n`; + result += ` Status: ${plan.status}\n`; + result += ` Source Asset: ${plan.sourceAsset}\n`; + result += ` Subscription Amount: ${plan.subscriptionAmount}\n`; + result += ` Cycle: ${plan.subscriptionCycle}\n`; + result += ` Next Execution: ${plan.nextExecutionDateTime || "N/A"}\n\n`; + + if (plan.details && Array.isArray(plan.details)) { + result += ` **Target Assets:**\n`; + plan.details.forEach((detail: any) => { + result += ` - ${detail.targetAsset}: ${detail.percentage}%\n`; + }); + result += "\n"; } + }); + } else { + result += `No auto-invest plans found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest plans: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getSourceAssetList.ts b/src/modules/auto-invest/getSourceAssetList.ts index 1920639a..1471132d 100644 --- a/src/modules/auto-invest/getSourceAssetList.ts +++ b/src/modules/auto-invest/getSourceAssetList.ts @@ -5,68 +5,83 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getSourceAssetList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetSourceAssetList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetSourceAssetList", + server.registerTool( + "BinanceAutoInvestGetSourceAssetList", + { + description: "Get the list of available source assets for auto-invest plans. These are the assets you can use to fund your recurring purchases.", - { - usageType: z.enum(["RECURRING", "ONE_TIME"]).optional().describe("Usage type filter"), - targetAsset: z.string().optional().describe("Filter by target asset"), - indexId: z.number().int().optional().describe("Index ID filter"), - flexibleAllowedToUse: z.boolean().optional().describe("Filter by flexible savings availability"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.sourceAssetList({ - ...(params.usageType && { usageType: params.usageType }), - ...(params.targetAsset && { targetAsset: params.targetAsset }), - ...(params.indexId && { indexId: params.indexId }), - ...(params.flexibleAllowedToUse !== undefined && { flexibleAllowedToUse: params.flexibleAllowedToUse }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Source Assets\n\n`; - - if (data.sourceAssetList && Array.isArray(data.sourceAssetList)) { - result += `Total: ${data.sourceAssetList.length} assets\n\n`; - data.sourceAssetList.forEach((asset: any) => { - result += `**${asset.sourceAsset}**\n`; - result += ` Free Amount: ${asset.freeAmount}\n`; - result += ` Min Amount: ${asset.minAmount}\n`; - result += ` Max Amount: ${asset.maxAmount}\n\n`; - }); - } else if (Array.isArray(data)) { - data.forEach((asset: any) => { - result += `**${asset.sourceAsset || asset.asset}**\n`; - result += ` Available: ${asset.freeAmount || 'N/A'}\n\n`; - }); - } else { - result += `Source Assets: ${JSON.stringify(data)}`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest source assets: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + usageType: z.enum(["RECURRING", "ONE_TIME"]).optional().describe("Usage type filter"), + targetAsset: z.string().optional().describe("Filter by target asset"), + indexId: z.number().int().optional().describe("Index ID filter"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Filter by flexible savings availability"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.querySourceAssetList({ + ...(params.usageType && { usageType: params.usageType }), + ...(params.targetAsset && { targetAsset: params.targetAsset }), + ...(params.indexId && { indexId: params.indexId }), + ...(params.flexibleAllowedToUse !== undefined && { + flexibleAllowedToUse: params.flexibleAllowedToUse, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Source Assets\n\n`; + + if (data.sourceAssetList && Array.isArray(data.sourceAssetList)) { + result += `Total: ${data.sourceAssetList.length} assets\n\n`; + data.sourceAssetList.forEach((asset: any) => { + result += `**${asset.sourceAsset}**\n`; + result += ` Free Amount: ${asset.freeAmount}\n`; + result += ` Min Amount: ${asset.minAmount}\n`; + result += ` Max Amount: ${asset.maxAmount}\n\n`; + }); + } else if (Array.isArray(data)) { + data.forEach((asset: any) => { + result += `**${asset.sourceAsset || asset.asset}**\n`; + result += ` Available: ${asset.freeAmount || "N/A"}\n\n`; + }); + } else { + result += `Source Assets: ${JSON.stringify(data)}`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest source assets: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getTargetAssetList.ts b/src/modules/auto-invest/getTargetAssetList.ts index 60e9104e..d80eafa6 100644 --- a/src/modules/auto-invest/getTargetAssetList.ts +++ b/src/modules/auto-invest/getTargetAssetList.ts @@ -5,65 +5,84 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getTargetAssetList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetTargetAssetList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetTargetAssetList", + server.registerTool( + "BinanceAutoInvestGetTargetAssetList", + { + description: "Get the list of available target assets for auto-invest plans. Shows assets available for dollar-cost averaging.", - { - targetAsset: z.string().optional().describe("Filter by specific target asset (e.g., 'BTC')"), - size: z.number().int().min(1).max(100).optional().describe("Number of results (default 10, max 100)"), - current: z.number().int().min(1).optional().describe("Page number (default 1)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.targetAssetList({ - ...(params.targetAsset && { targetAsset: params.targetAsset }), - ...(params.size && { size: params.size }), - ...(params.current && { current: params.current }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Target Assets\n\n`; - - if (data.data && Array.isArray(data.data) && data.data.length > 0) { - result += `Total assets: ${data.total || data.data.length}\n\n`; - data.data.forEach((asset: any) => { - result += `**${asset.targetAsset}**\n`; - result += ` ROI: ${asset.roiAndDimensionTypeList ? 'Available' : 'N/A'}\n`; - result += ` Available: ${asset.available !== false}\n\n`; - }); - } else if (Array.isArray(data) && data.length > 0) { - data.forEach((asset: any) => { - result += `**${asset.targetAsset || asset.asset}**\n`; - result += ` Available: ${asset.available !== false}\n\n`; - }); - } else { - result += `No target assets found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest target assets: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + targetAsset: z + .string() + .optional() + .describe("Filter by specific target asset (e.g., 'BTC')"), + size: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of results (default 10, max 100)"), + current: z.number().int().min(1).optional().describe("Page number (default 1)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getTargetAssetList({ + ...(params.targetAsset && { targetAsset: params.targetAsset }), + ...(params.size && { size: params.size }), + ...(params.current && { current: params.current }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Target Assets\n\n`; + + if (data.data && Array.isArray(data.data) && data.data.length > 0) { + result += `Total assets: ${data.total || data.data.length}\n\n`; + data.data.forEach((asset: any) => { + result += `**${asset.targetAsset}**\n`; + result += ` ROI: ${asset.roiAndDimensionTypeList ? "Available" : "N/A"}\n`; + result += ` Available: ${asset.available !== false}\n\n`; + }); + } else if (Array.isArray(data) && data.length > 0) { + data.forEach((asset: any) => { + result += `**${asset.targetAsset || asset.asset}**\n`; + result += ` Available: ${asset.available !== false}\n\n`; + }); + } else { + result += `No target assets found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest target assets: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/getTargetAssetRoiData.ts b/src/modules/auto-invest/getTargetAssetRoiData.ts index 530da996..8e1fef77 100644 --- a/src/modules/auto-invest/getTargetAssetRoiData.ts +++ b/src/modules/auto-invest/getTargetAssetRoiData.ts @@ -5,63 +5,74 @@ * @license Apache-2.0 */ // src/modules/auto-invest/getTargetAssetRoiData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestGetTargetAssetRoiData(server: McpServer) { - server.tool( - "BinanceAutoInvestGetTargetAssetRoiData", + server.registerTool( + "BinanceAutoInvestGetTargetAssetRoiData", + { + description: "Get ROI (Return on Investment) data for auto-invest target assets. Shows historical performance data.", - { - targetAsset: z.string().describe("Target asset (e.g., 'BTC')"), - hisRoiType: z.enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "SEVEN_DAY"]) - .describe("Historical ROI time period"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.targetAssetRoiList({ - targetAsset: params.targetAsset, - hisRoiType: params.hisRoiType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest ROI Data - ${params.targetAsset}\n\n`; - result += `Period: ${params.hisRoiType}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - data.forEach((item: any) => { - result += `Date: ${item.date}\n`; - result += ` Simulated ROI: ${item.simulatedRoi}%\n\n`; - }); - } else if (data.data && Array.isArray(data.data)) { - data.data.forEach((item: any) => { - result += `Date: ${item.date}\n`; - result += ` Simulated ROI: ${item.simulatedRoi}%\n\n`; - }); - } else { - result += `ROI Data: ${JSON.stringify(data)}`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get auto-invest ROI data: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + targetAsset: z.string().describe("Target asset (e.g., 'BTC')"), + hisRoiType: z + .enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "SEVEN_DAY"]) + .describe("Historical ROI time period"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getTargetAssetRoiData({ + targetAsset: params.targetAsset, + hisRoiType: params.hisRoiType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest ROI Data - ${params.targetAsset}\n\n`; + result += `Period: ${params.hisRoiType}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + data.forEach((item: any) => { + result += `Date: ${item.date}\n`; + result += ` Simulated ROI: ${item.simulatedRoi}%\n\n`; + }); + } else if (data.data && Array.isArray(data.data)) { + data.data.forEach((item: any) => { + result += `Date: ${item.date}\n`; + result += ` Simulated ROI: ${item.simulatedRoi}%\n\n`; + }); + } else { + result += `ROI Data: ${JSON.stringify(data)}`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get auto-invest ROI data: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/index.ts b/src/modules/auto-invest/index.ts index 06651cac..3054df49 100644 --- a/src/modules/auto-invest/index.ts +++ b/src/modules/auto-invest/index.ts @@ -1,7 +1,8 @@ // src/modules/auto-invest/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceAutoInvestTools } from "../../tools/binance-auto-invest/index.js"; export function registerAutoInvest(server: McpServer) { - registerBinanceAutoInvestTools(server); + registerBinanceAutoInvestTools(server); } diff --git a/src/modules/auto-invest/oneTimeTransaction.ts b/src/modules/auto-invest/oneTimeTransaction.ts index 5483cbb7..80b9f9ab 100644 --- a/src/modules/auto-invest/oneTimeTransaction.ts +++ b/src/modules/auto-invest/oneTimeTransaction.ts @@ -5,60 +5,79 @@ * @license Apache-2.0 */ // src/modules/auto-invest/oneTimeTransaction.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestOneTimeTransaction(server: McpServer) { - server.tool( - "BinanceAutoInvestOneTimeTransaction", + server.registerTool( + "BinanceAutoInvestOneTimeTransaction", + { + description: "Execute a one-time auto-invest purchase. Instantly buy crypto using auto-invest infrastructure.", - { - sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), - subscriptionAmount: z.string().describe("Amount to invest"), - sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), - flexibleAllowedToUse: z.boolean().optional() - .describe("Allow using flexible savings balance"), - planId: z.number().int().optional().describe("Plan ID for plan-based one-time purchase"), - indexId: z.number().int().optional().describe("Index ID for index-based purchase"), - details: z.array(z.object({ - targetAsset: z.string().describe("Target asset to purchase"), - percentage: z.number().describe("Percentage allocation (0-100)") - })).optional().describe("Target assets and allocation (for non-plan purchases)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const requestParams: any = { - sourceType: params.sourceType, - subscriptionAmount: params.subscriptionAmount, - sourceAsset: params.sourceAsset, - ...(params.flexibleAllowedToUse !== undefined && { flexibleAllowedToUse: params.flexibleAllowedToUse }), - ...(params.planId && { planId: params.planId }), - ...(params.indexId && { indexId: params.indexId }), - ...(params.details && { details: JSON.stringify(params.details) }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }; - - const response = await autoInvestClient.restAPI.oneOff(requestParams); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ One-time auto-invest purchase executed!\n\nTransaction ID: ${data.transactionId || data.tranId || 'Completed'}\nAmount: ${params.subscriptionAmount} ${params.sourceAsset}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to execute one-time purchase: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), + subscriptionAmount: z.string().describe("Amount to invest"), + sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Allow using flexible savings balance"), + planId: z.number().int().optional().describe("Plan ID for plan-based one-time purchase"), + indexId: z.number().int().optional().describe("Index ID for index-based purchase"), + details: z + .array( + z.object({ + targetAsset: z.string().describe("Target asset to purchase"), + percentage: z.number().describe("Percentage allocation (0-100)"), + }), + ) + .optional() + .describe("Target assets and allocation (for non-plan purchases)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const requestParams: any = { + sourceType: params.sourceType, + subscriptionAmount: params.subscriptionAmount, + sourceAsset: params.sourceAsset, + ...(params.flexibleAllowedToUse !== undefined && { + flexibleAllowedToUse: params.flexibleAllowedToUse, + }), + ...(params.planId && { planId: params.planId }), + ...(params.indexId && { indexId: params.indexId }), + ...(params.details && { details: JSON.stringify(params.details) }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }; + + const response = await (autoInvestClient as any).restAPI.oneTimeTransaction(requestParams); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ One-time auto-invest purchase executed!\n\nTransaction ID: ${data.transactionId || data.tranId || "Completed"}\nAmount: ${params.subscriptionAmount} ${params.sourceAsset}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to execute one-time purchase: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/rebalanceHistory.ts b/src/modules/auto-invest/rebalanceHistory.ts index 0bc1c447..b73f1861 100644 --- a/src/modules/auto-invest/rebalanceHistory.ts +++ b/src/modules/auto-invest/rebalanceHistory.ts @@ -5,68 +5,84 @@ * @license Apache-2.0 */ // src/modules/auto-invest/rebalanceHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestRebalanceHistory(server: McpServer) { - server.tool( - "BinanceAutoInvestRebalanceHistory", + server.registerTool( + "BinanceAutoInvestRebalanceHistory", + { + description: "Get auto-invest portfolio rebalance history. Shows past rebalancing transactions.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - size: z.number().int().min(1).max(100).optional().describe("Number of results (default 10, max 100)"), - current: z.number().int().min(1).optional().describe("Page number (default 1)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.rebalanceHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.size && { size: params.size }), - ...(params.current && { current: params.current }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Auto-Invest Rebalance History\n\n`; - - const history = data.list || data.data || data; - - if (Array.isArray(history) && history.length > 0) { - result += `Total rebalances: ${data.total || history.length}\n\n`; - history.forEach((rebalance: any, index: number) => { - result += `**${index + 1}. Rebalance ID: ${rebalance.id || rebalance.rebalanceId}**\n`; - result += ` Status: ${rebalance.status}\n`; - result += ` Time: ${rebalance.rebalanceDateTime || new Date(rebalance.time).toISOString()}\n`; - if (rebalance.details) { - result += ` Details: ${JSON.stringify(rebalance.details)}\n`; - } - result += '\n'; - }); - } else { - result += `No rebalance history found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get rebalance history: ${errorMessage}` - }], - isError: true - }; + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + size: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of results (default 10, max 100)"), + current: z.number().int().min(1).optional().describe("Page number (default 1)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.indexLinkedPlanRebalanceDetails({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.size && { size: params.size }), + ...(params.current && { current: params.current }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Auto-Invest Rebalance History\n\n`; + + const history = data.list || data.data || data; + + if (Array.isArray(history) && history.length > 0) { + result += `Total rebalances: ${data.total || history.length}\n\n`; + history.forEach((rebalance: any, index: number) => { + result += `**${index + 1}. Rebalance ID: ${rebalance.id || rebalance.rebalanceId}**\n`; + result += ` Status: ${rebalance.status}\n`; + result += ` Time: ${rebalance.rebalanceDateTime || new Date(rebalance.time).toISOString()}\n`; + if (rebalance.details) { + result += ` Details: ${JSON.stringify(rebalance.details)}\n`; } + result += "\n"; + }); + } else { + result += `No rebalance history found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get rebalance history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/auto-invest/redemption.ts b/src/modules/auto-invest/redemption.ts index 2a858dc7..66271120 100644 --- a/src/modules/auto-invest/redemption.ts +++ b/src/modules/auto-invest/redemption.ts @@ -5,45 +5,54 @@ * @license Apache-2.0 */ // src/modules/auto-invest/redemption.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerAutoInvestRedemption(server: McpServer) { - server.tool( - "BinanceAutoInvestRedemption", - "Redeem/sell assets from an auto-invest index plan.", - { - indexId: z.number().int().describe("Index ID to redeem from"), - redemptionPercentage: z.number().min(0).max(100).describe("Percentage to redeem (0-100)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.redeem({ - indexId: params.indexId, - redemptionPercentage: params.redemptionPercentage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Auto-invest redemption successful!\n\nIndex ID: ${params.indexId}\nRedemption Percentage: ${params.redemptionPercentage}%\nTransaction ID: ${data.transactionId || data.redemptionId || 'Completed'}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to redeem from auto-invest: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestRedemption", + { + description: "Redeem/sell assets from an auto-invest index plan.", + inputSchema: { + indexId: z.number().int().describe("Index ID to redeem from"), + redemptionPercentage: z.number().min(0).max(100).describe("Percentage to redeem (0-100)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.indexLinkedPlanRedemption({ + indexId: params.indexId, + redemptionPercentage: params.redemptionPercentage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Auto-invest redemption successful!\n\nIndex ID: ${params.indexId}\nRedemption Percentage: ${params.redemptionPercentage}%\nTransaction ID: ${data.transactionId || data.redemptionId || "Completed"}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to redeem from auto-invest: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/c2c/C2C/getAds.ts b/src/modules/c2c/C2C/getAds.ts index 13c8697b..d66dcc81 100644 --- a/src/modules/c2c/C2C/getAds.ts +++ b/src/modules/c2c/C2C/getAds.ts @@ -5,51 +5,61 @@ * @license Apache-2.0 */ // src/modules/c2c/C2C/getAds.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { c2cClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { c2cClient } from "../../../config/binanceClient.js"; + export function registerBinanceC2CGetAds(server: McpServer) { - server.tool( - "BinanceC2CGetAds", + server.registerTool( + "BinanceC2CGetAds", + { + description: "Get available C2C/P2P trading advertisements. Browse buy/sell offers from other users.", - { - asset: z.string().optional().describe("Filter by crypto asset (e.g., 'BTC', 'USDT')"), - fiat: z.string().optional().describe("Filter by fiat currency (e.g., 'USD', 'EUR')"), - tradeType: z.enum(["BUY", "SELL"]).optional().describe("Filter by trade type"), - page: z.number().int().min(1).default(1).optional().describe("Page number"), - rows: z.number().int().min(1).max(20).default(10).optional().describe("Number of rows"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await c2cClient.restAPI.getAds({ - ...(params.asset && { asset: params.asset }), - ...(params.fiat && { fiat: params.fiat }), - ...(params.tradeType && { tradeType: params.tradeType }), - ...(params.page && { page: params.page }), - ...(params.rows && { rows: params.rows }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by crypto asset (e.g., 'BTC', 'USDT')"), + fiat: z.string().optional().describe("Filter by fiat currency (e.g., 'USD', 'EUR')"), + tradeType: z.enum(["BUY", "SELL"]).optional().describe("Filter by trade type"), + page: z.number().int().min(1).default(1).optional().describe("Page number"), + rows: z.number().int().min(1).max(20).default(10).optional().describe("Number of rows"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (c2cClient as any).restAPI.getAds({ + ...(params.asset && { asset: params.asset }), + ...(params.fiat && { fiat: params.fiat }), + ...(params.tradeType && { tradeType: params.tradeType }), + ...(params.page && { page: params.page }), + ...(params.rows && { rows: params.rows }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📋 C2C Advertisements\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 C2C Advertisements\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get C2C ads: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get C2C ads: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/c2c/C2C/getC2CTradeHistory.ts b/src/modules/c2c/C2C/getC2CTradeHistory.ts index 1570b7ad..b7d007b5 100644 --- a/src/modules/c2c/C2C/getC2CTradeHistory.ts +++ b/src/modules/c2c/C2C/getC2CTradeHistory.ts @@ -1,48 +1,54 @@ // src/tools/binance-c2c/getC2CTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { c2cClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { c2cClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetC2CTradeHistory(server: McpServer) { - server.tool( - "BinanceGetC2CTradeHistory", + server.registerTool( + "BinanceGetC2CTradeHistory", + { + description: "Allows the user to retrieve their own past C2C trades, including details such as asset type, trade direction (BUY/SELL), fiat currency used, trade status, and more.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await c2cClient.restAPI.getC2CTradeHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.page !== undefined && { page: params.page }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await c2cClient.restAPI.getC2CTradeHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.page !== undefined && { page: params.page }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved the past C2C trades. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the past C2C trades. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve users past C2C trades: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve users past C2C trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/c2c/index.ts b/src/modules/c2c/index.ts index afe3e888..a450b1fe 100644 --- a/src/modules/c2c/index.ts +++ b/src/modules/c2c/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-c2c/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetC2CTradeHistory } from "./C2C/getC2CTradeHistory.js"; export function registerBinanceC2CTradeHistoryTools(server: McpServer) { - registerBinanceGetC2CTradeHistory(server); + registerBinanceGetC2CTradeHistory(server); } // Alias for binance.ts compatibility diff --git a/src/modules/convert/index.ts b/src/modules/convert/index.ts index 7a75053a..40d63ed8 100644 --- a/src/modules/convert/index.ts +++ b/src/modules/convert/index.ts @@ -1,14 +1,15 @@ // src/tools/binance-convert/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceConvertTradeTools } from "./trade-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertMarketDataTools } from "./market-data-api/index.js"; +import { registerBinanceConvertTradeTools } from "./trade-api/index.js"; export function registerBinanceConvertTools(server: McpServer) { - // Register tools for accessing market data from Binance Convert - registerBinanceConvertMarketDataTools(server); + // Register tools for accessing market data from Binance Convert + registerBinanceConvertMarketDataTools(server); - // Register tools for performing trades on Binance Convert - registerBinanceConvertTradeTools(server); + // Register tools for performing trades on Binance Convert + registerBinanceConvertTradeTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/convert/market-data-api/index.ts b/src/modules/convert/market-data-api/index.ts index 923f432b..325cb54b 100644 --- a/src/modules/convert/market-data-api/index.ts +++ b/src/modules/convert/market-data-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-convert/market-data-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceConvertQueryOrderQuantityPrecisionPerAsset } from "./queryOrderQuantityPrecisionPerAsset.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertGetListAllConvertPairs } from "./listAllConvertPairs.js"; +import { registerBinanceConvertQueryOrderQuantityPrecisionPerAsset } from "./queryOrderQuantityPrecisionPerAsset.js"; export function registerBinanceConvertMarketDataTools(server: McpServer) { - // Register the route to get a list of all supported convert trading pairs - registerBinanceConvertGetListAllConvertPairs(server); + // Register the route to get a list of all supported convert trading pairs + registerBinanceConvertGetListAllConvertPairs(server); - // Register the route to get quantity precision details for each asset - registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server); + // Register the route to get quantity precision details for each asset + registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server); } diff --git a/src/modules/convert/market-data-api/listAllConvertPairs.ts b/src/modules/convert/market-data-api/listAllConvertPairs.ts index 6f130319..08a9bb1f 100644 --- a/src/modules/convert/market-data-api/listAllConvertPairs.ts +++ b/src/modules/convert/market-data-api/listAllConvertPairs.ts @@ -1,45 +1,51 @@ // src/tools/binance-convert/market-data-api/listAllConvertPairs.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertGetListAllConvertPairs(server: McpServer) { - server.tool( - "BinanceConvertGetListAllConvertPairs", + server.registerTool( + "BinanceConvertGetListAllConvertPairs", + { + description: "Query available conversion pairs (like BTC to USDT), and shows the minimum and maximum allowed amounts for both the source and destination tokens.", - { - fromAsset: z.string().optional().describe("User spends coin"), - toAsset: z.string().optional().describe("User receives coin") - }, - async (params) => { - try { - const response = await convertClient.restAPI.listAllConvertPairs({ - ...(params.fromAsset && { fromAsset: params.fromAsset }), - ...(params.toAsset && { toAsset: params.toAsset }) - }); + inputSchema: { + fromAsset: z.string().optional().describe("User spends coin"), + toAsset: z.string().optional().describe("User receives coin"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.listAllConvertPairs({ + ...(params.fromAsset && { fromAsset: params.fromAsset }), + ...(params.toAsset && { toAsset: params.toAsset }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully queried available conversion pairs. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully queried available conversion pairs. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to query available conversion pairs: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to query available conversion pairs: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts b/src/modules/convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts index 27c59705..a37b5c20 100644 --- a/src/modules/convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts +++ b/src/modules/convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts @@ -1,50 +1,56 @@ // src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server: McpServer) { - server.tool( - "BinanceConvertQueryOrderQuantityPrecisionPerAsset", + server.registerTool( + "BinanceConvertQueryOrderQuantityPrecisionPerAsset", + { + description: "Retrieve decimal precision (fraction) information for each supported asset in the Convert feature.", - { - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.queryOrderQuantityPrecisionPerAsset({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.queryOrderQuantityPrecisionPerAsset({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved decimal precision information for each supported asset. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved decimal precision information for each supported asset. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve decimal precision (fraction) information: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve decimal precision (fraction) information: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/acceptQuote.ts b/src/modules/convert/trade-api/acceptQuote.ts index 50189a97..3df62cc2 100644 --- a/src/modules/convert/trade-api/acceptQuote.ts +++ b/src/modules/convert/trade-api/acceptQuote.ts @@ -1,49 +1,55 @@ // src/tools/binance-convert/trade-api/acceptQuote.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertAcceptQuote(server: McpServer) { - server.tool( - "BinanceConvertAcceptQuote", + server.registerTool( + "BinanceConvertAcceptQuote", + { + description: "The API confirms and executes a token conversion using a previously received quote ID.", - { - quoteId: z.string().describe("Quote ID"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.acceptQuote({ - quoteId: params.quoteId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + quoteId: z.string().describe("Quote ID"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.acceptQuote({ + quoteId: params.quoteId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully executed the token conversion. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully executed the token conversion. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to execute a token conversion : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to execute a token conversion : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/cancelLimitOrder.ts b/src/modules/convert/trade-api/cancelLimitOrder.ts index 0e960cc2..4da9c70d 100644 --- a/src/modules/convert/trade-api/cancelLimitOrder.ts +++ b/src/modules/convert/trade-api/cancelLimitOrder.ts @@ -1,49 +1,55 @@ // src/tools/binance-convert/trade-api/cancelLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertCancelLimitOrder(server: McpServer) { - server.tool( - "BinanceConvertCancelLimitOrder", + server.registerTool( + "BinanceConvertCancelLimitOrder", + { + description: "Cancels a previously placed limit order using the orderId and returns the cancellation status along with the orderId.", - { - orderId: z.number().int().describe("The orderId from placeOrder API"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.cancelLimitOrder({ - orderId: params.orderId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + orderId: z.number().int().describe("The orderId from placeOrder API"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.cancelLimitOrder({ + orderId: params.orderId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Canceled the placed limit order. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Canceled the placed limit order. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to placed limit order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to placed limit order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/getConvertTradeHistory.ts b/src/modules/convert/trade-api/getConvertTradeHistory.ts index 6da43a22..8c8fbe37 100644 --- a/src/modules/convert/trade-api/getConvertTradeHistory.ts +++ b/src/modules/convert/trade-api/getConvertTradeHistory.ts @@ -1,56 +1,62 @@ // src/tools/binance-convert/trade-api/getConvertTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetConvertTradeHistory(server: McpServer) { - server.tool( - "BinanceGetConvertTradeHistory", + server.registerTool( + "BinanceGetConvertTradeHistory", + { + description: "The API retrieves your token conversion trade history within a specified time range, with support for pagination using the limit parameter (up to 1000 records).", - { - startTime: z.number().int().describe("Start time in milliseconds"), - endTime: z.number().int().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(1000, "Limit cannot be greater than 1000") - .optional() - .describe("Default 100, Max 1000"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.getConvertTradeHistory({ - startTime: params.startTime, - endTime: params.endTime, - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().describe("Start time in milliseconds"), + endTime: z.number().int().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(1000, "Limit cannot be greater than 1000") + .optional() + .describe("Default 100, Max 1000"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.getConvertTradeHistory({ + startTime: params.startTime, + endTime: params.endTime, + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved your token conversion trade history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved your token conversion trade history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve your token conversion: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve your token conversion: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/index.ts b/src/modules/convert/trade-api/index.ts index a7efa11e..86128d99 100644 --- a/src/modules/convert/trade-api/index.ts +++ b/src/modules/convert/trade-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-convert/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertAcceptQuote } from "./acceptQuote.js"; import { registerBinanceConvertCancelLimitOrder } from "./cancelLimitOrder.js"; import { registerBinanceGetConvertTradeHistory } from "./getConvertTradeHistory.js"; @@ -9,24 +10,24 @@ import { registerBinanceConvertQueryLimitOpenOrders } from "./queryLimitOpenOrde import { registerBinanceConvertSendQuoteRequest } from "./sendQuoteRequest.js"; export function registerBinanceConvertTradeTools(server: McpServer) { - // Register the route to accept a quote for a convert trade - registerBinanceConvertAcceptQuote(server); + // Register the route to accept a quote for a convert trade + registerBinanceConvertAcceptQuote(server); - // Register the route to cancel an existing convert limit order - registerBinanceConvertCancelLimitOrder(server); + // Register the route to cancel an existing convert limit order + registerBinanceConvertCancelLimitOrder(server); - // Register the route to get the convert trade history - registerBinanceGetConvertTradeHistory(server); + // Register the route to get the convert trade history + registerBinanceGetConvertTradeHistory(server); - // Register the route to check the status of a convert order - registerBinanceConvertOrderStatus(server); + // Register the route to check the status of a convert order + registerBinanceConvertOrderStatus(server); - // Register the route to place a new convert limit order - registerBinanceConvertPlaceLimitOrder(server); + // Register the route to place a new convert limit order + registerBinanceConvertPlaceLimitOrder(server); - // Register the route to query currently open convert limit orders - registerBinanceConvertQueryLimitOpenOrders(server); + // Register the route to query currently open convert limit orders + registerBinanceConvertQueryLimitOpenOrders(server); - // Register the route to send a quote request for a convert trade - registerBinanceConvertSendQuoteRequest(server); + // Register the route to send a quote request for a convert trade + registerBinanceConvertSendQuoteRequest(server); } diff --git a/src/modules/convert/trade-api/orderStatus.ts b/src/modules/convert/trade-api/orderStatus.ts index 72d4b323..32ee7073 100644 --- a/src/modules/convert/trade-api/orderStatus.ts +++ b/src/modules/convert/trade-api/orderStatus.ts @@ -1,47 +1,53 @@ // src/tools/binance-convert/trade-api/orderStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertOrderStatus(server: McpServer) { - server.tool( - "BinanceConvertOrderStatus", + server.registerTool( + "BinanceConvertOrderStatus", + { + description: "The API checks the status of a token conversion order using either the orderId or quoteId, and returns details like conversion status, assets involved, amounts, exchange rate, and order creation time.", - { - orderId: z.string().optional().describe("Order ID (either this or quoteId is required)"), - quoteId: z.string().optional().describe("Quote ID (either this or orderId is required)") - }, - async (params) => { - try { - const response = await convertClient.restAPI.orderStatus({ - ...(params.orderId && { orderId: params.orderId }), - ...(params.quoteId && { quoteId: params.quoteId }) - }); + inputSchema: { + orderId: z.string().optional().describe("Order ID (either this or quoteId is required)"), + quoteId: z.string().optional().describe("Quote ID (either this or orderId is required)"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.orderStatus({ + ...(params.orderId && { orderId: params.orderId }), + ...(params.quoteId && { quoteId: params.quoteId }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully get the status of a token conversion . Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully get the status of a token conversion . Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to check the status: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to check the status: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/placeLimitOrder.ts b/src/modules/convert/trade-api/placeLimitOrder.ts index 42fb17f1..2639e773 100644 --- a/src/modules/convert/trade-api/placeLimitOrder.ts +++ b/src/modules/convert/trade-api/placeLimitOrder.ts @@ -1,77 +1,86 @@ // src/tools/binance-convert/trade-api/placeLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertPlaceLimitOrder(server: McpServer) { - server.tool( - "BinanceConvertPlaceLimitOrder", + server.registerTool( + "BinanceConvertPlaceLimitOrder", + { + description: "Places a limit order to convert between two tokens at a specified price, using either base or quote amount, with options for wallet type and order expiry.", - { - baseAsset: z.string().describe("Base asset (from `fromIsBase` in /exchangeInfo API)"), - quoteAsset: z.string().describe("Quote asset"), - limitPrice: z.number().positive().describe("Symbol limit price (from baseAsset to quoteAsset)"), - baseAmount: z - .number() - .positive() - .optional() - .describe("Base asset amount (either this or quoteAmount is required)"), - quoteAmount: z - .number() - .positive() - .optional() - .describe("Quote asset amount (either this or baseAmount is required)"), - side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), - walletType: z - .enum(["SPOT", "FUNDING", "SPOT_FUNDING"]) - .optional() - .describe("Type of assets used: SPOT, FUNDING, or SPOT_FUNDING. Default is SPOT"), - expiredType: z - .enum(["1_D", "3_D", "7_D", "30_D"]) - .describe("Expiration type: 1_D, 3_D, 7_D, or 30_D (D = days)"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.placeLimitOrder({ - baseAsset: params.baseAsset, - quoteAsset: params.quoteAsset, - limitPrice: params.limitPrice, - side: params.side, - expiredType: params.expiredType, - ...(params.baseAmount !== undefined && { baseAmount: params.baseAmount }), - ...(params.quoteAmount !== undefined && { quoteAmount: params.quoteAmount }), - ...(params.walletType && { walletType: params.walletType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + baseAsset: z.string().describe("Base asset (from `fromIsBase` in /exchangeInfo API)"), + quoteAsset: z.string().describe("Quote asset"), + limitPrice: z + .number() + .positive() + .describe("Symbol limit price (from baseAsset to quoteAsset)"), + baseAmount: z + .number() + .positive() + .optional() + .describe("Base asset amount (either this or quoteAmount is required)"), + quoteAmount: z + .number() + .positive() + .optional() + .describe("Quote asset amount (either this or baseAmount is required)"), + side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), + walletType: z + .enum(["SPOT", "FUNDING", "SPOT_FUNDING"]) + .optional() + .describe("Type of assets used: SPOT, FUNDING, or SPOT_FUNDING. Default is SPOT"), + expiredType: z + .enum(["1_D", "3_D", "7_D", "30_D"]) + .describe("Expiration type: 1_D, 3_D, 7_D, or 30_D (D = days)"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.placeLimitOrder({ + baseAsset: params.baseAsset, + quoteAsset: params.quoteAsset, + limitPrice: params.limitPrice, + side: params.side, + expiredType: params.expiredType, + ...(params.baseAmount !== undefined && { baseAmount: params.baseAmount }), + ...(params.quoteAmount !== undefined && { quoteAmount: params.quoteAmount }), + ...(params.walletType && { walletType: params.walletType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully placed the limit order. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully placed the limit order. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to places a limit order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to places a limit order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/queryLimitOpenOrders.ts b/src/modules/convert/trade-api/queryLimitOpenOrders.ts index c397279c..d96ede06 100644 --- a/src/modules/convert/trade-api/queryLimitOpenOrders.ts +++ b/src/modules/convert/trade-api/queryLimitOpenOrders.ts @@ -1,50 +1,56 @@ // src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertQueryLimitOpenOrders(server: McpServer) { - server.tool( - "BinanceConvertQueryLimitOpenOrders", + server.registerTool( + "BinanceConvertQueryLimitOpenOrders", + { + description: "Retrieves all your open limit orders for token conversions, showing details like assets, amounts, exchange rate, order status, and expiration time.", - { - recvWindow: z - .number() - .int() - .max(60000, "recvWindow must not be greater than 60000") - .optional() - .describe("This value must not exceed 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.queryLimitOpenOrders({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000, "recvWindow must not be greater than 60000") + .optional() + .describe("This value must not exceed 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.queryLimitOpenOrders({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved all the open limit orders for token conversions. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved all the open limit orders for token conversions. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve all your open limit orders : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve all your open limit orders : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/convert/trade-api/sendQuoteRequest.ts b/src/modules/convert/trade-api/sendQuoteRequest.ts index d3594f0c..c564cdc3 100644 --- a/src/modules/convert/trade-api/sendQuoteRequest.ts +++ b/src/modules/convert/trade-api/sendQuoteRequest.ts @@ -1,65 +1,82 @@ // src/tools/binance-convert/trade-api/sendQuoteRequest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertSendQuoteRequest(server: McpServer) { - server.tool( - "BinanceConvertSendQuoteRequest", + server.registerTool( + "BinanceConvertSendQuoteRequest", + { + description: "Get a real-time quote to convert one token to another, including rate and amount, if you have enough funds.", - { - fromAsset: z.string().describe("Asset you will spend (required)"), - toAsset: z.string().describe("Asset you will receive (required)"), - fromAmount: z.number().positive().optional().describe("Amount to be debited after conversion"), - toAmount: z.number().positive().optional().describe("Amount to be credited after conversion"), - walletType: z.enum(["SPOT", "FUNDING"]).optional().describe("SPOT or FUNDING. Default is SPOT"), - validTime: z - .enum(["10s", "30s", "1m"]) - .optional() - .describe("Quote validity duration: 10s, 30s, 1m; default is 10s"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.sendQuoteRequest({ - fromAsset: params.fromAsset, - toAsset: params.toAsset, - ...(params.fromAmount && { fromAmount: params.fromAmount }), - ...(params.toAmount && { toAmount: params.toAmount }), - ...(params.walletType && { walletType: params.walletType }), - ...(params.validTime && { validTime: params.validTime }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + fromAsset: z.string().describe("Asset you will spend (required)"), + toAsset: z.string().describe("Asset you will receive (required)"), + fromAmount: z + .number() + .positive() + .optional() + .describe("Amount to be debited after conversion"), + toAmount: z + .number() + .positive() + .optional() + .describe("Amount to be credited after conversion"), + walletType: z + .enum(["SPOT", "FUNDING"]) + .optional() + .describe("SPOT or FUNDING. Default is SPOT"), + validTime: z + .enum(["10s", "30s", "1m"]) + .optional() + .describe("Quote validity duration: 10s, 30s, 1m; default is 10s"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.sendQuoteRequest({ + fromAsset: params.fromAsset, + toAsset: params.toAsset, + ...(params.fromAmount && { fromAmount: params.fromAmount }), + ...(params.toAmount && { toAmount: params.toAmount }), + ...(params.walletType && { walletType: params.walletType }), + ...(params.validTime && { validTime: params.validTime }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved real-time quote to convert one token to another. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved real-time quote to convert one token to another. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to get a real-time quote to convert: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to get a real-time quote to convert: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/followTrader.ts b/src/modules/copy-trading/FutureCopyTrading-api/followTrader.ts index 68c469d3..68573a44 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/followTrader.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/followTrader.ts @@ -5,53 +5,73 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/followTrader.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingFollowTrader(server: McpServer) { - server.tool( - "BinanceCopyTradingFollowTrader", + server.registerTool( + "BinanceCopyTradingFollowTrader", + { + description: "Start following a lead trader to automatically copy their trades. ⚠️ RISK: Your funds will be used to copy trades. Only follow traders you trust.", - { - leadPortfolioId: z.string().describe("Lead trader's portfolio ID to follow"), - copyRatio: z.number().min(0.1).max(10).describe("Copy ratio (0.1-10x of their trades)"), - fixedAmount: z.string().optional().describe("Fixed amount per trade (alternative to ratio)"), - stopLossRatio: z.number().min(0.01).max(1).optional() - .describe("Stop loss ratio (e.g., 0.1 = stop if 10% loss)"), - takeProfitRatio: z.number().min(0.01).optional() - .describe("Take profit ratio (e.g., 0.5 = take profit at 50% gain)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.followTrader({ - leadPortfolioId: params.leadPortfolioId, - copyRatio: params.copyRatio, - ...(params.fixedAmount && { fixedAmount: params.fixedAmount }), - ...(params.stopLossRatio && { stopLossRatio: params.stopLossRatio }), - ...(params.takeProfitRatio && { takeProfitRatio: params.takeProfitRatio }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + leadPortfolioId: z.string().describe("Lead trader's portfolio ID to follow"), + copyRatio: z.number().min(0.1).max(10).describe("Copy ratio (0.1-10x of their trades)"), + fixedAmount: z + .string() + .optional() + .describe("Fixed amount per trade (alternative to ratio)"), + stopLossRatio: z + .number() + .min(0.01) + .max(1) + .optional() + .describe("Stop loss ratio (e.g., 0.1 = stop if 10% loss)"), + takeProfitRatio: z + .number() + .min(0.01) + .optional() + .describe("Take profit ratio (e.g., 0.5 = take profit at 50% gain)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.followTrader({ + leadPortfolioId: params.leadPortfolioId, + copyRatio: params.copyRatio, + ...(params.fixedAmount && { fixedAmount: params.fixedAmount }), + ...(params.stopLossRatio && { stopLossRatio: params.stopLossRatio }), + ...(params.takeProfitRatio && { takeProfitRatio: params.takeProfitRatio }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const _data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Now Following Trader!\n\nPortfolio: ${params.leadPortfolioId}\nCopy Ratio: ${params.copyRatio}x\nStop Loss: ${params.stopLossRatio ? params.stopLossRatio * 100 + "%" : "Not set"}\nTake Profit: ${params.takeProfitRatio ? params.takeProfitRatio * 100 + "%" : "Not set"}\n\n⚠️ Your trades will now automatically copy this trader.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Now Following Trader!\n\nPortfolio: ${params.leadPortfolioId}\nCopy Ratio: ${params.copyRatio}x\nStop Loss: ${params.stopLossRatio ? (params.stopLossRatio * 100) + '%' : 'Not set'}\nTake Profit: ${params.takeProfitRatio ? (params.takeProfitRatio * 100) + '%' : 'Not set'}\n\n⚠️ Your trades will now automatically copy this trader.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to follow trader: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to follow trader: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getCopyOrders.ts b/src/modules/copy-trading/FutureCopyTrading-api/getCopyOrders.ts index c2f2a36f..33d1dd38 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getCopyOrders.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getCopyOrders.ts @@ -5,49 +5,59 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getCopyOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetCopyOrders(server: McpServer) { - server.tool( - "BinanceCopyTradingGetCopyOrders", + server.registerTool( + "BinanceCopyTradingGetCopyOrders", + { + description: "Get your copy trading order history. Shows all orders executed from copying lead traders.", - { - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - pageNumber: z.number().int().min(1).default(1).optional().describe("Page number"), - pageSize: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getCopyOrders({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.pageNumber && { pageNumber: params.pageNumber }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + pageNumber: z.number().int().min(1).default(1).optional().describe("Page number"), + pageSize: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getCopyOrders({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.pageNumber && { pageNumber: params.pageNumber }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📋 Copy Trading Orders\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 Copy Trading Orders\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get copy orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get copy orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getCopyPositions.ts b/src/modules/copy-trading/FutureCopyTrading-api/getCopyPositions.ts index 52644037..04df359d 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getCopyPositions.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getCopyPositions.ts @@ -5,41 +5,51 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getCopyPositions.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetCopyPositions(server: McpServer) { - server.tool( - "BinanceCopyTradingGetCopyPositions", + server.registerTool( + "BinanceCopyTradingGetCopyPositions", + { + description: "Get your current positions from copy trading. Shows all open positions created by following lead traders.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getCopyPositions({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getCopyPositions({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📈 Your Copy Trading Positions\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📈 Your Copy Trading Positions\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get copy positions: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get copy positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getFollowingTraders.ts b/src/modules/copy-trading/FutureCopyTrading-api/getFollowingTraders.ts index 91ce27a0..ebe1619a 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getFollowingTraders.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getFollowingTraders.ts @@ -5,41 +5,51 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getFollowingTraders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetFollowingTraders(server: McpServer) { - server.tool( - "BinanceCopyTradingGetFollowingTraders", + server.registerTool( + "BinanceCopyTradingGetFollowingTraders", + { + description: "Get the list of traders you are currently following. Shows copy settings and performance for each.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFollowingTraders({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getFollowingTraders({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `👥 Traders You're Following\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `👥 Traders You're Following\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get following traders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get following traders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts b/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts index def3b5f3..5c58fabe 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts @@ -1,45 +1,55 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFuturesLeadTraderStatus(server: McpServer) { - server.tool( - "BinanceGetFuturesLeadTraderStatus", + server.registerTool( + "BinanceGetFuturesLeadTraderStatus", + { + description: "Checks and returns whether the user is currently a Futures Lead Trader in Binance Copy Trading, along with the timestamp of the status check.", - { - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFuturesLeadTraderStatus({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getFuturesLeadTraderStatus({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved user futures trading details. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved user futures trading details. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Check and return whether the user is currently a Futures Lead Trader in Binance Copy Trading: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Check and return whether the user is currently a Futures Lead Trader in Binance Copy Trading: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts b/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts index 09399375..9c9be5f6 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts @@ -1,43 +1,55 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFuturesLeadTradingSymbolWhitelist(server: McpServer) { - server.tool( - "BinanceGetFuturesLeadTradingSymbolWhitelist", + server.registerTool( + "BinanceGetFuturesLeadTradingSymbolWhitelist", + { + description: "Whitelist of trading pairs (symbols) that are allowed for Futures Lead Traders in copy trading, including base and quote assets.", - { - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFuturesLeadTradingSymbolWhitelist({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await ( + copyTradingClient as any + ).restAPI.getFuturesLeadTradingSymbolWhitelist({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved trading pairs. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved trading pairs. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to whitelist of trading pairs: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to whitelist of trading pairs: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getLeadTraders.ts b/src/modules/copy-trading/FutureCopyTrading-api/getLeadTraders.ts index ddde5634..4b313d06 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getLeadTraders.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getLeadTraders.ts @@ -5,49 +5,59 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getLeadTraders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetLeadTraders(server: McpServer) { - server.tool( - "BinanceCopyTradingGetLeadTraders", + server.registerTool( + "BinanceCopyTradingGetLeadTraders", + { + description: "Browse available lead traders for copy trading. View their performance stats and follower count to find traders to copy.", - { - isShared: z.boolean().optional().describe("Filter by shared portfolio traders"), - tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type filter"), - pageNumber: z.number().int().min(1).default(1).optional().describe("Page number"), - pageSize: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getLeadTraders({ - ...(params.isShared !== undefined && { isShared: params.isShared }), - ...(params.tradeType && { tradeType: params.tradeType }), - ...(params.pageNumber && { pageNumber: params.pageNumber }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + isShared: z.boolean().optional().describe("Filter by shared portfolio traders"), + tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type filter"), + pageNumber: z.number().int().min(1).default(1).optional().describe("Page number"), + pageSize: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getLeadTraders({ + ...(params.isShared !== undefined && { isShared: params.isShared }), + ...(params.tradeType && { tradeType: params.tradeType }), + ...(params.pageNumber && { pageNumber: params.pageNumber }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `👥 Lead Traders\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `👥 Lead Traders\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get lead traders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get lead traders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getTraderPerformance.ts b/src/modules/copy-trading/FutureCopyTrading-api/getTraderPerformance.ts index 7d72ea80..183f33ea 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getTraderPerformance.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getTraderPerformance.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getTraderPerformance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetTraderPerformance(server: McpServer) { - server.tool( - "BinanceCopyTradingGetTraderPerformance", + server.registerTool( + "BinanceCopyTradingGetTraderPerformance", + { + description: "Get detailed performance statistics for a lead trader. Includes ROI, PNL, win rate, and other metrics.", - { - leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), - tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getTraderPerformance({ - leadPortfolioId: params.leadPortfolioId, - ...(params.tradeType && { tradeType: params.tradeType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), + tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getTraderPerformance({ + leadPortfolioId: params.leadPortfolioId, + ...(params.tradeType && { tradeType: params.tradeType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Trader Performance\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Trader Performance\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get trader performance: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get trader performance: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getTraderPositions.ts b/src/modules/copy-trading/FutureCopyTrading-api/getTraderPositions.ts index 37294f80..f4f20e12 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getTraderPositions.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getTraderPositions.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getTraderPositions.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetTraderPositions(server: McpServer) { - server.tool( - "BinanceCopyTradingGetTraderPositions", + server.registerTool( + "BinanceCopyTradingGetTraderPositions", + { + description: "View a lead trader's current open positions. See what positions they are holding to understand their strategy.", - { - leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), - tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getTraderPositions({ - leadPortfolioId: params.leadPortfolioId, - ...(params.tradeType && { tradeType: params.tradeType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), + tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getTraderPositions({ + leadPortfolioId: params.leadPortfolioId, + ...(params.tradeType && { tradeType: params.tradeType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📈 Trader Positions\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📈 Trader Positions\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get trader positions: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get trader positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/getTraderSymbolStats.ts b/src/modules/copy-trading/FutureCopyTrading-api/getTraderSymbolStats.ts index e9d9f4e3..e3a5bc20 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/getTraderSymbolStats.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/getTraderSymbolStats.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/getTraderSymbolStats.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetTraderSymbolStats(server: McpServer) { - server.tool( - "BinanceCopyTradingGetTraderSymbolStats", + server.registerTool( + "BinanceCopyTradingGetTraderSymbolStats", + { + description: "Get a lead trader's trading statistics per symbol. Shows which symbols they trade most and their success rate.", - { - leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), - tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getTraderSymbolStats({ - leadPortfolioId: params.leadPortfolioId, - ...(params.tradeType && { tradeType: params.tradeType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + leadPortfolioId: z.string().describe("Lead trader's portfolio ID"), + tradeType: z.enum(["PERPETUAL"]).optional().describe("Trade type"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getTraderSymbolStats({ + leadPortfolioId: params.leadPortfolioId, + ...(params.tradeType && { tradeType: params.tradeType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Trader Symbol Statistics\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Trader Symbol Statistics\n\nPortfolio: ${params.leadPortfolioId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get trader symbol stats: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get trader symbol stats: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/index.ts b/src/modules/copy-trading/FutureCopyTrading-api/index.ts index 486470c3..27f03171 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/index.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFuturesLeadTraderStatus } from "./getFuturesLeadTraderStatus.js"; import { registerBinanceGetFuturesLeadTradingSymbolWhitelist } from "./getFuturesLeadTradingSymbolWhitelist.js"; // Registers Binance Futures Copy Trading API tools with the MCP server. export function registerBinanceFutureCopyTradingApiTools(server: McpServer) { - // Registers an endpoint to get the status of a lead trader in futures copy trading - registerBinanceGetFuturesLeadTraderStatus(server); + // Registers an endpoint to get the status of a lead trader in futures copy trading + registerBinanceGetFuturesLeadTraderStatus(server); - // Registers an endpoint to get the whitelist of symbols available for futures copy trading - registerBinanceGetFuturesLeadTradingSymbolWhitelist(server); + // Registers an endpoint to get the whitelist of symbols available for futures copy trading + registerBinanceGetFuturesLeadTradingSymbolWhitelist(server); } diff --git a/src/modules/copy-trading/FutureCopyTrading-api/unfollowTrader.ts b/src/modules/copy-trading/FutureCopyTrading-api/unfollowTrader.ts index abdf5426..16fd2edd 100644 --- a/src/modules/copy-trading/FutureCopyTrading-api/unfollowTrader.ts +++ b/src/modules/copy-trading/FutureCopyTrading-api/unfollowTrader.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/copy-trading/FutureCopyTrading-api/unfollowTrader.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingUnfollowTrader(server: McpServer) { - server.tool( - "BinanceCopyTradingUnfollowTrader", + server.registerTool( + "BinanceCopyTradingUnfollowTrader", + { + description: "Stop following a lead trader. Your existing copied positions will remain open until manually closed.", - { - leadPortfolioId: z.string().describe("Lead trader's portfolio ID to unfollow"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.unfollowTrader({ - leadPortfolioId: params.leadPortfolioId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + leadPortfolioId: z.string().describe("Lead trader's portfolio ID to unfollow"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.unfollowTrader({ + leadPortfolioId: params.leadPortfolioId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const _data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Stopped Following Trader!\n\nPortfolio: ${params.leadPortfolioId}\n\n💡 Note: Existing positions from copy trading are still open. You may want to close them manually.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Stopped Following Trader!\n\nPortfolio: ${params.leadPortfolioId}\n\n💡 Note: Existing positions from copy trading are still open. You may want to close them manually.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to unfollow trader: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to unfollow trader: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/copy-trading/index.ts b/src/modules/copy-trading/index.ts index fc607ffa..47d93dc3 100644 --- a/src/modules/copy-trading/index.ts +++ b/src/modules/copy-trading/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-copy-trading/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFutureCopyTradingApiTools } from "./FutureCopyTrading-api/index.js"; // Registers all Binance Copy Trading related tools with the MCP server. export function registerBinanceCopyTradingTools(server: McpServer) { - // Register the Binance Futures Copy Trading API tools with the given server. - registerBinanceFutureCopyTradingApiTools(server); + // Register the Binance Futures Copy Trading API tools with the given server. + registerBinanceFutureCopyTradingApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/crypto-loans/flexible/adjustLTV.ts b/src/modules/crypto-loans/flexible/adjustLTV.ts index df400e4d..31361aba 100644 --- a/src/modules/crypto-loans/flexible/adjustLTV.ts +++ b/src/modules/crypto-loans/flexible/adjustLTV.ts @@ -5,49 +5,61 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/adjustLTV.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanAdjustLTV(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleAdjustLTV", + server.registerTool( + "BinanceCryptoLoanFlexibleAdjustLTV", + { + description: "Adjust LTV (Loan-to-Value) ratio by adding or removing collateral. Lower LTV = safer position.", - { - loanCoin: z.string().describe("Loan coin"), - collateralCoin: z.string().describe("Collateral coin"), - adjustmentAmount: z.string().describe("Amount to add (positive) or remove (negative)"), - direction: z.enum(["ADDITIONAL", "REDUCED"]).describe("ADDITIONAL to add collateral, REDUCED to remove"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.flexibleLoanAdjustLTV({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - adjustmentAmount: params.adjustmentAmount, - direction: params.direction, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Loan coin"), + collateralCoin: z.string().describe("Collateral coin"), + adjustmentAmount: z.string().describe("Amount to add (positive) or remove (negative)"), + direction: z + .enum(["ADDITIONAL", "REDUCED"]) + .describe("ADDITIONAL to add collateral, REDUCED to remove"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanAdjustLtv({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + adjustmentAmount: params.adjustmentAmount, + direction: params.direction, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ LTV Adjusted!\n\nDirection: ${params.direction}\nAmount: ${params.adjustmentAmount} ${params.collateralCoin}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ LTV Adjusted!\n\nDirection: ${params.direction}\nAmount: ${params.adjustmentAmount} ${params.collateralCoin}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to adjust LTV: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to adjust LTV: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/borrow.ts b/src/modules/crypto-loans/flexible/borrow.ts index e5ec8ad6..efc0da96 100644 --- a/src/modules/crypto-loans/flexible/borrow.ts +++ b/src/modules/crypto-loans/flexible/borrow.ts @@ -5,49 +5,65 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/borrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanBorrow(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleBorrow", + server.registerTool( + "BinanceCryptoLoanFlexibleBorrow", + { + description: "Borrow crypto using a flexible loan. ⚠️ Your collateral will be locked. Interest accrues daily. Monitor LTV ratio to avoid liquidation.", - { - loanCoin: z.string().describe("Coin to borrow (e.g., 'USDT')"), - loanAmount: z.string().optional().describe("Amount to borrow (provide either loanAmount or collateralAmount)"), - collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC')"), - collateralAmount: z.string().optional().describe("Collateral amount (provide either loanAmount or collateralAmount)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.flexibleLoanBorrow({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - ...(params.loanAmount && { loanAmount: params.loanAmount }), - ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Coin to borrow (e.g., 'USDT')"), + loanAmount: z + .string() + .optional() + .describe("Amount to borrow (provide either loanAmount or collateralAmount)"), + collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC')"), + collateralAmount: z + .string() + .optional() + .describe("Collateral amount (provide either loanAmount or collateralAmount)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanBorrow({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + ...(params.loanAmount && { loanAmount: params.loanAmount }), + ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Flexible Loan Borrowed!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\n\n⚠️ Remember to monitor your LTV ratio and repay to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Flexible Loan Borrowed!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\n\n⚠️ Remember to monitor your LTV ratio and repay to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to borrow: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to borrow: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/getBorrowHistory.ts b/src/modules/crypto-loans/flexible/getBorrowHistory.ts index e18acb61..c2d78b47 100644 --- a/src/modules/crypto-loans/flexible/getBorrowHistory.ts +++ b/src/modules/crypto-loans/flexible/getBorrowHistory.ts @@ -5,53 +5,62 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/getBorrowHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanBorrowHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleBorrowHistory", - "Get your flexible loan borrowing history.", - { - loanCoin: z.string().optional().describe("Filter by loan coin"), - collateralCoin: z.string().optional().describe("Filter by collateral coin"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanBorrowHistory({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoanFlexibleBorrowHistory", + { + description: "Get your flexible loan borrowing history.", + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanBorrowHistory({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Flexible Loan Borrow History\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Flexible Loan Borrow History\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get borrow history: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get borrow history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/getFlexibleCollateralAssets.ts b/src/modules/crypto-loans/flexible/getFlexibleCollateralAssets.ts index 93989ff4..1dc9b362 100644 --- a/src/modules/crypto-loans/flexible/getFlexibleCollateralAssets.ts +++ b/src/modules/crypto-loans/flexible/getFlexibleCollateralAssets.ts @@ -5,43 +5,55 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/getFlexibleCollateralAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleCollateralAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleCollateralAssets", + server.registerTool( + "BinanceCryptoLoanFlexibleCollateralAssets", + { + description: "Get available collateral assets for flexible crypto loans. Shows which assets you can use as collateral.", - { - collateralCoin: z.string().optional().describe("Filter by collateral coin"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleCollateralAssets({ - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await ( + cryptoLoanClient as any + ).restAPI.getFlexibleLoanCollateralAssetsData({ + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `🔒 Flexible Loan Collateral Assets\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `🔒 Flexible Loan Collateral Assets\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get collateral assets: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get collateral assets: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/getFlexibleLoanAssets.ts b/src/modules/crypto-loans/flexible/getFlexibleLoanAssets.ts index 91c0e497..13ad31c7 100644 --- a/src/modules/crypto-loans/flexible/getFlexibleLoanAssets.ts +++ b/src/modules/crypto-loans/flexible/getFlexibleLoanAssets.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/getFlexibleLoanAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleAssets", + server.registerTool( + "BinanceCryptoLoanFlexibleAssets", + { + description: "Get available assets for flexible crypto loans. Shows which assets you can borrow and their rates.", - { - loanCoin: z.string().optional().describe("Filter by loan coin (e.g., 'USDT', 'BUSD')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanAssets({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin (e.g., 'USDT', 'BUSD')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanAssetsData({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `💰 Flexible Loan Assets\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `💰 Flexible Loan Assets\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get flexible loan assets: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get flexible loan assets: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/getOngoingOrders.ts b/src/modules/crypto-loans/flexible/getOngoingOrders.ts index dd0a5fbf..11a685d9 100644 --- a/src/modules/crypto-loans/flexible/getOngoingOrders.ts +++ b/src/modules/crypto-loans/flexible/getOngoingOrders.ts @@ -5,49 +5,59 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/getOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanOngoingOrders(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleOngoingOrders", + server.registerTool( + "BinanceCryptoLoanFlexibleOngoingOrders", + { + description: "Get your current flexible loan positions. Shows outstanding amounts, collateral, and LTV ratios.", - { - loanCoin: z.string().optional().describe("Filter by loan coin"), - collateralCoin: z.string().optional().describe("Filter by collateral coin"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanOngoingOrders({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanOngoingOrders({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Ongoing Flexible Loans\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Ongoing Flexible Loans\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get ongoing orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get ongoing orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/getRepayHistory.ts b/src/modules/crypto-loans/flexible/getRepayHistory.ts index b86353b5..6d658ac6 100644 --- a/src/modules/crypto-loans/flexible/getRepayHistory.ts +++ b/src/modules/crypto-loans/flexible/getRepayHistory.ts @@ -5,53 +5,62 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/getRepayHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanRepayHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleRepayHistory", - "Get your flexible loan repayment history.", - { - loanCoin: z.string().optional().describe("Filter by loan coin"), - collateralCoin: z.string().optional().describe("Filter by collateral coin"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanRepayHistory({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoanFlexibleRepayHistory", + { + description: "Get your flexible loan repayment history.", + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + limit: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanRepaymentHistory({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Flexible Loan Repay History\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Flexible Loan Repay History\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get repay history: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get repay history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/flexible/index.ts b/src/modules/crypto-loans/flexible/index.ts index c267589e..8ea04b2c 100644 --- a/src/modules/crypto-loans/flexible/index.ts +++ b/src/modules/crypto-loans/flexible/index.ts @@ -5,23 +5,24 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerFlexibleLoanAssets } from "./getFlexibleLoanAssets.js"; -import { registerFlexibleCollateralAssets } from "./getFlexibleCollateralAssets.js"; -import { registerFlexibleLoanBorrow } from "./borrow.js"; -import { registerFlexibleLoanRepay } from "./repay.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerFlexibleLoanAdjustLTV } from "./adjustLTV.js"; -import { registerFlexibleLoanOngoingOrders } from "./getOngoingOrders.js"; +import { registerFlexibleLoanBorrow } from "./borrow.js"; import { registerFlexibleLoanBorrowHistory } from "./getBorrowHistory.js"; +import { registerFlexibleCollateralAssets } from "./getFlexibleCollateralAssets.js"; +import { registerFlexibleLoanAssets } from "./getFlexibleLoanAssets.js"; +import { registerFlexibleLoanOngoingOrders } from "./getOngoingOrders.js"; import { registerFlexibleLoanRepayHistory } from "./getRepayHistory.js"; +import { registerFlexibleLoanRepay } from "./repay.js"; export function registerCryptoLoansFlexibleTools(server: McpServer) { - registerFlexibleLoanAssets(server); - registerFlexibleCollateralAssets(server); - registerFlexibleLoanBorrow(server); - registerFlexibleLoanRepay(server); - registerFlexibleLoanAdjustLTV(server); - registerFlexibleLoanOngoingOrders(server); - registerFlexibleLoanBorrowHistory(server); - registerFlexibleLoanRepayHistory(server); + registerFlexibleLoanAssets(server); + registerFlexibleCollateralAssets(server); + registerFlexibleLoanBorrow(server); + registerFlexibleLoanRepay(server); + registerFlexibleLoanAdjustLTV(server); + registerFlexibleLoanOngoingOrders(server); + registerFlexibleLoanBorrowHistory(server); + registerFlexibleLoanRepayHistory(server); } diff --git a/src/modules/crypto-loans/flexible/repay.ts b/src/modules/crypto-loans/flexible/repay.ts index 1412b6a8..ba977bd2 100644 --- a/src/modules/crypto-loans/flexible/repay.ts +++ b/src/modules/crypto-loans/flexible/repay.ts @@ -5,51 +5,63 @@ * @license Apache-2.0 */ // src/modules/crypto-loans/flexible/repay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerFlexibleLoanRepay(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleRepay", + server.registerTool( + "BinanceCryptoLoanFlexibleRepay", + { + description: "Repay a flexible crypto loan. Your collateral will be released proportionally. 💸", - { - loanCoin: z.string().describe("Loan coin to repay"), - collateralCoin: z.string().describe("Collateral coin"), - repayAmount: z.string().describe("Amount to repay"), - collateralReturn: z.boolean().optional().describe("Return collateral after full repayment"), - fullRepayment: z.boolean().optional().describe("Repay full outstanding amount"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.flexibleLoanRepay({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - repayAmount: params.repayAmount, - ...(params.collateralReturn !== undefined && { collateralReturn: params.collateralReturn }), - ...(params.fullRepayment !== undefined && { fullRepayment: params.fullRepayment }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Loan coin to repay"), + collateralCoin: z.string().describe("Collateral coin"), + repayAmount: z.string().describe("Amount to repay"), + collateralReturn: z.boolean().optional().describe("Return collateral after full repayment"), + fullRepayment: z.boolean().optional().describe("Repay full outstanding amount"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanRepay({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + repayAmount: params.repayAmount, + ...(params.collateralReturn !== undefined && { + collateralReturn: params.collateralReturn, + }), + ...(params.fullRepayment !== undefined && { fullRepayment: params.fullRepayment }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Loan Repayment Successful!\n\nRepaid: ${params.repayAmount} ${params.loanCoin}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Loan Repayment Successful!\n\nRepaid: ${params.repayAmount} ${params.loanCoin}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to repay loan: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to repay loan: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/crypto-loans/index.ts b/src/modules/crypto-loans/index.ts index b0e7ae92..9070882b 100644 --- a/src/modules/crypto-loans/index.ts +++ b/src/modules/crypto-loans/index.ts @@ -1,7 +1,8 @@ // src/modules/crypto-loans/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCryptoLoansTools } from "../../tools/binance-crypto-loans/index.js"; export function registerCryptoLoans(server: McpServer) { - registerBinanceCryptoLoansTools(server); + registerBinanceCryptoLoansTools(server); } diff --git a/src/modules/dual-investment/index.ts b/src/modules/dual-investment/index.ts index d3c2e381..5b1a0b12 100644 --- a/src/modules/dual-investment/index.ts +++ b/src/modules/dual-investment/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-dual-investment/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDualInvestmentTradeApiTools } from "./trade-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDualInvestmentMarketApiTools } from "./market-api/index.js"; +import { registerBinanceDualInvestmentTradeApiTools } from "./trade-api/index.js"; export function registerBinanceDualInvestmentTools(server: McpServer) { - registerBinanceDualInvestmentTradeApiTools(server); - registerBinanceDualInvestmentMarketApiTools(server); + registerBinanceDualInvestmentTradeApiTools(server); + registerBinanceDualInvestmentMarketApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/dual-investment/market-api/getDualInvestmentProductList.ts b/src/modules/dual-investment/market-api/getDualInvestmentProductList.ts index 048f342d..3676a381 100644 --- a/src/modules/dual-investment/market-api/getDualInvestmentProductList.ts +++ b/src/modules/dual-investment/market-api/getDualInvestmentProductList.ts @@ -1,66 +1,72 @@ // src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetDualInvestmentProductList(server: McpServer) { - server.tool( - "BinanceGetDualInvestmentProductList", + server.registerTool( + "BinanceGetDualInvestmentProductList", + { + description: "Retrieve available Dual Investment products (CALL or PUT options), specifying invest and exercised coins, to view details like APR, strike price, duration, and purchase availability.", - { - optionType: z.enum(["CALL", "PUT"]).describe("Input CALL or PUT"), - exercisedCoin: z.string().describe("Target exercised asset, e.g., USDT or BNB"), - investCoin: z.string().describe("Asset used for subscribing, e.g., BNB or USDT"), - pageSize: z - .number() - .int() - .max(100, "Maximum pageSize is 100") - .default(10) - .optional() - .describe("Number of records per page, default 10, max 100"), - pageIndex: z.number().int().default(1).optional().describe("Page index, default is 1"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.getDualInvestmentProductList({ - optionType: params.optionType, - exercisedCoin: params.exercisedCoin, - investCoin: params.investCoin, - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + optionType: z.enum(["CALL", "PUT"]).describe("Input CALL or PUT"), + exercisedCoin: z.string().describe("Target exercised asset, e.g., USDT or BNB"), + investCoin: z.string().describe("Asset used for subscribing, e.g., BNB or USDT"), + pageSize: z + .number() + .int() + .max(100, "Maximum pageSize is 100") + .default(10) + .optional() + .describe("Number of records per page, default 10, max 100"), + pageIndex: z.number().int().default(1).optional().describe("Page index, default is 1"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.getDualInvestmentProductList({ + optionType: params.optionType, + exercisedCoin: params.exercisedCoin, + investCoin: params.investCoin, + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved available Dual Investment products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved available Dual Investment products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve available Dual Investment products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve available Dual Investment products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/dual-investment/market-api/index.ts b/src/modules/dual-investment/market-api/index.ts index 5b6b81f2..f5465f8a 100644 --- a/src/modules/dual-investment/market-api/index.ts +++ b/src/modules/dual-investment/market-api/index.ts @@ -1,7 +1,8 @@ // src/tools/binance-dual-investment/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetDualInvestmentProductList } from "./getDualInvestmentProductList.js"; export function registerBinanceDualInvestmentMarketApiTools(server: McpServer) { - registerBinanceGetDualInvestmentProductList(server); + registerBinanceGetDualInvestmentProductList(server); } diff --git a/src/modules/dual-investment/trade-api/changeAutoCompoundStatus.ts b/src/modules/dual-investment/trade-api/changeAutoCompoundStatus.ts index 8904f7b9..888ad64b 100644 --- a/src/modules/dual-investment/trade-api/changeAutoCompoundStatus.ts +++ b/src/modules/dual-investment/trade-api/changeAutoCompoundStatus.ts @@ -1,57 +1,63 @@ // src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceChangeAutoCompoundStatus(server: McpServer) { - server.tool( - "registerBinanceChangeAutoCompoundStatus", + server.registerTool( + "registerBinanceChangeAutoCompoundStatus", + { + description: "Change the Auto-Compound plan for a Dual Investment position to NONE, STANDARD, or ADVANCED using the position ID.", - { - positionId: z.string().describe("Get positionId from /sapi/v1/dci/product/positions"), - autoCompoundPlan: z - .enum(["NONE", "STANDARD", "ADVANCED"]) - .optional() - .describe("Auto compound plan: NONE, STANDARD, or ADVANCED"), - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.changeAutoCompoundStatus({ - positionId: params.positionId, - autoCompoundPlan: params.autoCompoundPlan, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + positionId: z.string().describe("Get positionId from /sapi/v1/dci/product/positions"), + autoCompoundPlan: z + .enum(["NONE", "STANDARD", "ADVANCED"]) + .optional() + .describe("Auto compound plan: NONE, STANDARD, or ADVANCED"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.changeAutoCompoundStatus({ + positionId: params.positionId, + autoCompoundPlan: params.autoCompoundPlan, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Changed the Auto-Compound plan for a Dual Investment position. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Changed the Auto-Compound plan for a Dual Investment position. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to change the Auto-Compound plan for a Dual Investment position: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to change the Auto-Compound plan for a Dual Investment position: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/dual-investment/trade-api/checkDualInvestmentAccounts.ts b/src/modules/dual-investment/trade-api/checkDualInvestmentAccounts.ts index 0026a009..cca74369 100644 --- a/src/modules/dual-investment/trade-api/checkDualInvestmentAccounts.ts +++ b/src/modules/dual-investment/trade-api/checkDualInvestmentAccounts.ts @@ -1,50 +1,56 @@ // src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceCheckDualInvestmentAccounts(server: McpServer) { - server.tool( - "BinanceCheckDualInvestmentAccounts", + server.registerTool( + "BinanceCheckDualInvestmentAccounts", + { + description: "Retrieve Dual Investment account balances, including total value in BTC and USDT equivalents.", - { - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.checkDualInvestmentAccounts({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.checkDualInvestmentAccounts({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve Dual Investment account balances, including total value in BTC and USDT equivalents. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve Dual Investment account balances, including total value in BTC and USDT equivalents. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve Dual Investment account balances: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve Dual Investment account balances: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/dual-investment/trade-api/getDualInvestmentPositions.ts b/src/modules/dual-investment/trade-api/getDualInvestmentPositions.ts index 824c169e..34115870 100644 --- a/src/modules/dual-investment/trade-api/getDualInvestmentPositions.ts +++ b/src/modules/dual-investment/trade-api/getDualInvestmentPositions.ts @@ -1,75 +1,81 @@ // src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetDualInvestmentPositions(server: McpServer) { - server.tool( - "BinanceGetDualInvestmentPositions", + server.registerTool( + "BinanceGetDualInvestmentPositions", + { + description: "Fetch Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Filter by status or paginate results.", - { - status: z - .enum([ - "PENDING", - "PURCHASE_SUCCESS", - "SETTLED", - "PURCHASE_FAIL", - "REFUNDING", - "REFUND_SUCCESS", - "SETTLING" - ]) - .optional() - .describe( - "Position status: PENDING (awaiting results), PURCHASE_SUCCESS, SETTLED, PURCHASE_FAIL, REFUNDING, REFUND_SUCCESS, or SETTLING. If not provided, returns all." - ), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .optional() - .describe("Number of items per page, default 10, max 100"), - pageIndex: z.number().int().min(1).optional().describe("Page index, default 1"), - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.getDualInvestmentPositions({ - ...(params.status && { status: params.status }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + status: z + .enum([ + "PENDING", + "PURCHASE_SUCCESS", + "SETTLED", + "PURCHASE_FAIL", + "REFUNDING", + "REFUND_SUCCESS", + "SETTLING", + ]) + .optional() + .describe( + "Position status: PENDING (awaiting results), PURCHASE_SUCCESS, SETTLED, PURCHASE_FAIL, REFUNDING, REFUND_SUCCESS, or SETTLING. If not provided, returns all.", + ), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of items per page, default 10, max 100"), + pageIndex: z.number().int().min(1).optional().describe("Page index, default 1"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.getDualInvestmentPositions({ + ...(params.status && { status: params.status }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Fetched Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Fetched Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetch dual investment positions: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetch dual investment positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/dual-investment/trade-api/index.ts b/src/modules/dual-investment/trade-api/index.ts index 5e0692bf..97d55f6c 100644 --- a/src/modules/dual-investment/trade-api/index.ts +++ b/src/modules/dual-investment/trade-api/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-dual-investment/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubscribeDualInvestmentProducts } from "./subscribeDualInvestmentProducts.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceChangeAutoCompoundStatus } from "./changeAutoCompoundStatus.js"; import { registerBinanceCheckDualInvestmentAccounts } from "./checkDualInvestmentAccounts.js"; import { registerBinanceGetDualInvestmentPositions } from "./getDualInvestmentPositions.js"; -import { registerBinanceChangeAutoCompoundStatus } from "./changeAutoCompoundStatus.js"; +import { registerBinanceSubscribeDualInvestmentProducts } from "./subscribeDualInvestmentProducts.js"; export function registerBinanceDualInvestmentTradeApiTools(server: McpServer) { - registerBinanceSubscribeDualInvestmentProducts(server); - registerBinanceCheckDualInvestmentAccounts(server); - registerBinanceGetDualInvestmentPositions(server); - registerBinanceChangeAutoCompoundStatus(server); + registerBinanceSubscribeDualInvestmentProducts(server); + registerBinanceCheckDualInvestmentAccounts(server); + registerBinanceGetDualInvestmentPositions(server); + registerBinanceChangeAutoCompoundStatus(server); } diff --git a/src/modules/dual-investment/trade-api/subscribeDualInvestmentProducts.ts b/src/modules/dual-investment/trade-api/subscribeDualInvestmentProducts.ts index 36fa6626..5f84f4d4 100644 --- a/src/modules/dual-investment/trade-api/subscribeDualInvestmentProducts.ts +++ b/src/modules/dual-investment/trade-api/subscribeDualInvestmentProducts.ts @@ -1,60 +1,66 @@ // src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeDualInvestmentProducts(server: McpServer) { - server.tool( - "BinanceSubscribeDualInvestmentProducts", + server.registerTool( + "BinanceSubscribeDualInvestmentProducts", + { + description: "Subscribe to Dual Investment products by providing product ID, order ID, deposit amount, and auto compound plan to initiate investment with specified terms.", - { - id: z.string().describe("Product ID from /sapi/v1/dci/product/list"), - orderId: z.string().describe("Order ID from /sapi/v1/dci/product/list"), - depositAmount: z.number().positive().describe("The amount for subscribing"), - autoCompoundPlan: z - .enum(["NONE", "STANDARD", "ADVANCED"]) - .describe("Auto-compound plan: NONE (off), STANDARD, or ADVANCED"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.subscribeDualInvestmentProducts({ - id: params.id, - orderId: params.orderId, - depositAmount: params.depositAmount, - autoCompoundPlan: params.autoCompoundPlan, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + id: z.string().describe("Product ID from /sapi/v1/dci/product/list"), + orderId: z.string().describe("Order ID from /sapi/v1/dci/product/list"), + depositAmount: z.number().positive().describe("The amount for subscribing"), + autoCompoundPlan: z + .enum(["NONE", "STANDARD", "ADVANCED"]) + .describe("Auto-compound plan: NONE (off), STANDARD, or ADVANCED"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.subscribeDualInvestmentProducts({ + id: params.id, + orderId: params.orderId, + depositAmount: params.depositAmount, + autoCompoundPlan: params.autoCompoundPlan, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully subscribed to Dual Investment products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully subscribed to Dual Investment products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to subscribe to dual investment products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to subscribe to dual investment products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/fiat/fiat-api/getFiatDepositWithdrawHistory.ts b/src/modules/fiat/fiat-api/getFiatDepositWithdrawHistory.ts index feff9fbb..9b7e5f96 100644 --- a/src/modules/fiat/fiat-api/getFiatDepositWithdrawHistory.ts +++ b/src/modules/fiat/fiat-api/getFiatDepositWithdrawHistory.ts @@ -1,60 +1,72 @@ // src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { fiatClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { fiatClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFiatDepositWithdrawHistory(server: McpServer) { - server.tool( - "BinanceGetFiatDepositWithdrawHistory", + server.registerTool( + "BinanceGetFiatDepositWithdrawHistory", + { + description: "Fetches fiat deposit or withdrawal history, showing transaction details like amount, currency, method, status, and timestamps.", - { - transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for deposit, 1 for withdraw"), - beginTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - rows: z - .number() - .int() - .max(500, "Rows cannot be greater than 500") - .optional() - .describe("Number of records per page, default 100, max 500"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await fiatClient.restAPI.getFiatDepositWithdrawHistory({ - transactionType: params.transactionType, - ...(params.beginTime && { beginTime: params.beginTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.rows && { rows: params.rows }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + transactionType: z + .enum(["0", "1"]) + .describe("Transaction type: 0 for deposit, 1 for withdraw"), + beginTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + rows: z + .number() + .int() + .max(500, "Rows cannot be greater than 500") + .optional() + .describe("Number of records per page, default 100, max 500"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await fiatClient.restAPI.getFiatDepositWithdrawHistory({ + transactionType: params.transactionType, + ...(params.beginTime && { beginTime: params.beginTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.rows && { rows: params.rows }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched fiat deposit or withdrawal history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched fiat deposit or withdrawal history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetches fiat deposit or withdrawal history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetches fiat deposit or withdrawal history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/fiat/fiat-api/getFiatPaymentsHistory.ts b/src/modules/fiat/fiat-api/getFiatPaymentsHistory.ts index 330a61a3..b2e4a1dc 100644 --- a/src/modules/fiat/fiat-api/getFiatPaymentsHistory.ts +++ b/src/modules/fiat/fiat-api/getFiatPaymentsHistory.ts @@ -1,60 +1,70 @@ // src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { fiatClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { fiatClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFiatPaymentsHistory(server: McpServer) { - server.tool( - "BinanceGetFiatPaymentsHistory", + server.registerTool( + "BinanceGetFiatPaymentsHistory", + { + description: "Retrieves fiat buy/sell payment history, including trade amount, currency, crypto received, fees, status, payment method, and timestamps.", - { - transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for buy, 1 for sell"), - beginTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - rows: z - .number() - .int() - .max(500, "Rows cannot be greater than 500") - .optional() - .describe("Number of records per page, default 100, max 500"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await fiatClient.restAPI.getFiatPaymentsHistory({ - transactionType: params.transactionType, - ...(params.beginTime && { beginTime: params.beginTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.rows && { rows: params.rows }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for buy, 1 for sell"), + beginTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + rows: z + .number() + .int() + .max(500, "Rows cannot be greater than 500") + .optional() + .describe("Number of records per page, default 100, max 500"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await fiatClient.restAPI.getFiatPaymentsHistory({ + transactionType: params.transactionType, + ...(params.beginTime && { beginTime: params.beginTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.rows && { rows: params.rows }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved fiat buy/sell payment history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved fiat buy/sell payment history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve fiat buy/sell payment history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve fiat buy/sell payment history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/fiat/index.ts b/src/modules/fiat/index.ts index 5103765b..bda7e93b 100644 --- a/src/modules/fiat/index.ts +++ b/src/modules/fiat/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-fiat/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFiatDepositWithdrawHistory } from "./fiat-api/getFiatDepositWithdrawHistory.js"; import { registerBinanceGetFiatPaymentsHistory } from "./fiat-api/getFiatPaymentsHistory.js"; export function registerBinanceFiatDepositWithdrawHistoryTools(server: McpServer) { - registerBinanceGetFiatDepositWithdrawHistory(server); - registerBinanceGetFiatPaymentsHistory(server); + registerBinanceGetFiatDepositWithdrawHistory(server); + registerBinanceGetFiatPaymentsHistory(server); } // Alias for binance.ts compatibility diff --git a/src/modules/futures-coinm/index.ts b/src/modules/futures-coinm/index.ts index 31b6765e..918d049a 100644 --- a/src/modules/futures-coinm/index.ts +++ b/src/modules/futures-coinm/index.ts @@ -1,7 +1,8 @@ // src/modules/futures-coinm/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFuturesCOINMTools } from "../../tools/binance-futures-coinm/index.js"; export function registerFuturesCOINM(server: McpServer) { - registerBinanceFuturesCOINMTools(server); + registerBinanceFuturesCOINMTools(server); } diff --git a/src/modules/futures-usdm/index.ts b/src/modules/futures-usdm/index.ts index 1a476f2e..940524d0 100644 --- a/src/modules/futures-usdm/index.ts +++ b/src/modules/futures-usdm/index.ts @@ -1,7 +1,8 @@ // src/modules/futures-usdm/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFuturesUSDMTools } from "../../tools/binance-futures-usdm/index.js"; export function registerFuturesUSDM(server: McpServer) { - registerBinanceFuturesUSDMTools(server); + registerBinanceFuturesUSDMTools(server); } diff --git a/src/modules/gift-card/index.ts b/src/modules/gift-card/index.ts index ac98394b..88cdbe38 100644 --- a/src/modules/gift-card/index.ts +++ b/src/modules/gift-card/index.ts @@ -1,7 +1,8 @@ // src/modules/gift-card/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGiftCardTools } from "../../tools/binance-gift-card/index.js"; export function registerGiftCard(server: McpServer) { - registerBinanceGiftCardTools(server); + registerBinanceGiftCardTools(server); } diff --git a/src/modules/margin/index.ts b/src/modules/margin/index.ts index f2713925..c1e4cdc7 100644 --- a/src/modules/margin/index.ts +++ b/src/modules/margin/index.ts @@ -1,7 +1,8 @@ // src/modules/margin/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceMarginTools } from "../../tools/binance-margin/index.js"; export function registerMargin(server: McpServer) { - registerBinanceMarginTools(server); + registerBinanceMarginTools(server); } diff --git a/src/modules/mining/index.ts b/src/modules/mining/index.ts index 2119488e..c77b10a6 100644 --- a/src/modules/mining/index.ts +++ b/src/modules/mining/index.ts @@ -1,33 +1,34 @@ // src/tools/binance-mining/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountList } from "./mining-api/accountList.js"; import { registerBinanceAcquiringAlgorithm } from "./mining-api/acquiringAlgorithm.js"; import { registerBinanceAcquiringCoinName } from "./mining-api/acquiringCoinname.js"; -import { registerBinanceHashRateResaleList } from "./mining-api/hashrateResaleList.js"; -import { registerBinanceRequestForMinerList } from "./mining-api/requestForMinerList.js"; -import { registerBinanceRequestForDetailMinerList } from "./mining-api/requestForDetailMinerList.js"; -import { registerBinanceExtraBonusList } from "./mining-api/extraBonusList.js"; -import { registerBinanceEarningsList } from "./mining-api/earningsList.js"; import { registerBinanceCancelHashRateResaleConfiguration } from "./mining-api/cancelHashrateResaleConfiguration.js"; +import { registerBinanceEarningsList } from "./mining-api/earningsList.js"; +import { registerBinanceExtraBonusList } from "./mining-api/extraBonusList.js"; import { registerBinanceHashRateResaleDetail } from "./mining-api/hashrateResaleDetail.js"; +import { registerBinanceHashRateResaleList } from "./mining-api/hashrateResaleList.js"; +import { registerBinanceHashRateResaleRequest } from "./mining-api/hashrateResaleRequest.js"; import { registerBinanceMiningAccountEarning } from "./mining-api/miningAccountEarning.js"; +import { registerBinanceRequestForDetailMinerList } from "./mining-api/requestForDetailMinerList.js"; +import { registerBinanceRequestForMinerList } from "./mining-api/requestForMinerList.js"; import { registerBinanceStatisticList } from "./mining-api/statisticList.js"; -import { registerBinanceHashRateResaleRequest } from "./mining-api/hashrateResaleRequest.js"; -import { registerBinanceAccountList } from "./mining-api/accountList.js"; export function registerBinanceMiningTools(server: McpServer) { - registerBinanceAcquiringAlgorithm(server); - registerBinanceAcquiringCoinName(server); - registerBinanceHashRateResaleList(server); - registerBinanceRequestForMinerList(server); - registerBinanceRequestForDetailMinerList(server); - registerBinanceExtraBonusList(server); - registerBinanceEarningsList(server); - registerBinanceCancelHashRateResaleConfiguration(server); - registerBinanceHashRateResaleDetail(server); - registerBinanceMiningAccountEarning(server); - registerBinanceStatisticList(server); - registerBinanceHashRateResaleRequest(server); - registerBinanceAccountList(server); + registerBinanceAcquiringAlgorithm(server); + registerBinanceAcquiringCoinName(server); + registerBinanceHashRateResaleList(server); + registerBinanceRequestForMinerList(server); + registerBinanceRequestForDetailMinerList(server); + registerBinanceExtraBonusList(server); + registerBinanceEarningsList(server); + registerBinanceCancelHashRateResaleConfiguration(server); + registerBinanceHashRateResaleDetail(server); + registerBinanceMiningAccountEarning(server); + registerBinanceStatisticList(server); + registerBinanceHashRateResaleRequest(server); + registerBinanceAccountList(server); } // Alias for binance.ts compatibility diff --git a/src/modules/mining/mining-api/accountList.ts b/src/modules/mining/mining-api/accountList.ts index 068013a9..cff3381d 100644 --- a/src/modules/mining/mining-api/accountList.ts +++ b/src/modules/mining/mining-api/accountList.ts @@ -1,49 +1,59 @@ // src/tools/binance-mining/mining-api/accountList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceAccountList(server: McpServer) { - server.tool( - "BinanceAccountList", + server.registerTool( + "BinanceAccountList", + { + description: "Retrieve hashrate statistics for a mining account. It returns both hourly (H_hashrate) and daily (D_hashrate) data, including timestamps, hashrate values, and rejection rates.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.accountList({ - algo: params.algo, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.accountList({ + algo: params.algo, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved hashrate statistics for a mining account.. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved hashrate statistics for a mining account.. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve hashrate statistics for a mining account.. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve hashrate statistics for a mining account.. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/acquiringAlgorithm.ts b/src/modules/mining/mining-api/acquiringAlgorithm.ts index 0aef5307..df7ed419 100644 --- a/src/modules/mining/mining-api/acquiringAlgorithm.ts +++ b/src/modules/mining/mining-api/acquiringAlgorithm.ts @@ -1,40 +1,44 @@ // src/tools/binance-mining/mining-api/acquiringAlgorithm.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { miningClient } from "../../../config/binanceClient.js"; export function registerBinanceAcquiringAlgorithm(server: McpServer) { - server.tool( - "BinanceAcquiringAlgorithm", + server.registerTool( + "BinanceAcquiringAlgorithm", + { + description: "Retrieve a list of available mining algorithms, including their name, ID, sequence, and unit.", - {}, - async () => { - try { - const response = await miningClient.restAPI.acquiringAlgorithm(); + }, + async () => { + try { + const response = await miningClient.restAPI.acquiringAlgorithm(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve a list of available mining algorithms. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve a list of available mining algorithms. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of available mining algorithms: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of available mining algorithms: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/acquiringCoinname.ts b/src/modules/mining/mining-api/acquiringCoinname.ts index ef422b24..852f5276 100644 --- a/src/modules/mining/mining-api/acquiringCoinname.ts +++ b/src/modules/mining/mining-api/acquiringCoinname.ts @@ -1,38 +1,42 @@ // src/tools/binance-mining/mining-api/acquiringCoinname.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { miningClient } from "../../../config/binanceClient.js"; export function registerBinanceAcquiringCoinName(server: McpServer) { - server.tool( - "BinanceAcquiringCoinName", + server.registerTool( + "BinanceAcquiringCoinName", + { + description: "Fetch supported mining coins with details like coin name, ID, algorithm name, and associated algorithm ID.", - {}, - async () => { - try { - const response = await miningClient.restAPI.acquiringCoinname(); + }, + async () => { + try { + const response = await miningClient.restAPI.acquiringCoinname(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched supported mining coins. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched supported mining coins. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetched supported mining coins: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetched supported mining coins: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/cancelHashrateResaleConfiguration.ts b/src/modules/mining/mining-api/cancelHashrateResaleConfiguration.ts index 1caed1c1..0db4a335 100644 --- a/src/modules/mining/mining-api/cancelHashrateResaleConfiguration.ts +++ b/src/modules/mining/mining-api/cancelHashrateResaleConfiguration.ts @@ -1,49 +1,55 @@ // src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceCancelHashRateResaleConfiguration(server: McpServer) { - server.tool( - "BinanceCancelHashRateResaleConfiguration", + server.registerTool( + "BinanceCancelHashRateResaleConfiguration", + { + description: "Cancel an existing hashrate resale configuration using the mining ID and account details.", - { - configId: z.number().int().describe("Mining ID").min(1), - userName: z.string().min(1).describe("Mining Account"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.cancelHashrateResaleConfiguration({ - configId: params.configId, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + configId: z.number().int().describe("Mining ID").min(1), + userName: z.string().min(1).describe("Mining Account"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.cancelHashrateResaleConfiguration({ + configId: params.configId, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully canceled an existing hashrate resale configuration. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully canceled an existing hashrate resale configuration. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to canceled an existing hashrate resale configuration. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to canceled an existing hashrate resale configuration. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/earningsList.ts b/src/modules/mining/mining-api/earningsList.ts index 06a4740b..5067ff6c 100644 --- a/src/modules/mining/mining-api/earningsList.ts +++ b/src/modules/mining/mining-api/earningsList.ts @@ -1,64 +1,82 @@ // src/tools/binance-mining/mining-api/earningsList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceEarningsList(server: McpServer) { - server.tool( - "BinanceEarningsList", + server.registerTool( + "BinanceEarningsList", + { + description: "Retrieves list of earnings related to mining activities, including transferred hashrate, daily hashrate, profit amount, and the status of the payment (unpaid, paying, or paid).", - { - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - coin: z.string().optional().describe("Coin name (optional)"), - startDate: z.number().optional().describe("Search start date (milliseconds timestamp, optional)"), - endDate: z.number().optional().describe("Search end date (milliseconds timestamp, optional)"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.earningsList({ - algo: params.algo, - userName: params.userName, - ...(params.coin && { coin: params.coin }), - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + coin: z.string().optional().describe("Coin name (optional)"), + startDate: z + .number() + .optional() + .describe("Search start date (milliseconds timestamp, optional)"), + endDate: z + .number() + .optional() + .describe("Search end date (milliseconds timestamp, optional)"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.earningsList({ + algo: params.algo, + userName: params.userName, + ...(params.coin && { coin: params.coin }), + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved list of earnings related to mining activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved list of earnings related to mining activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve list of earnings related to mining activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve list of earnings related to mining activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/extraBonusList.ts b/src/modules/mining/mining-api/extraBonusList.ts index 0a46c53b..fa6c330d 100644 --- a/src/modules/mining/mining-api/extraBonusList.ts +++ b/src/modules/mining/mining-api/extraBonusList.ts @@ -1,58 +1,76 @@ // src/tools/binance-mining/mining-api/extraBonusList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceExtraBonusList(server: McpServer) { - server.tool( - "BinanceExtraBonusList", + server.registerTool( + "BinanceExtraBonusList", + { + description: "Retrieves extra bonuses related to mining activities, including merged mining, activity bonuses, rebates, smart pool bonuses, income transfers, and pool savings.", - { - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - coin: z.string().optional().describe("Coin name (optional)"), - startDate: z.number().optional().describe("Search start date (milliseconds timestamp, optional)"), - endDate: z.number().optional().describe("Search end date (milliseconds timestamp, optional)"), - pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.extraBonusList({ - algo: params.algo, - userName: params.userName, - ...(params.coin && { coin: params.coin }), - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + coin: z.string().optional().describe("Coin name (optional)"), + startDate: z + .number() + .optional() + .describe("Search start date (milliseconds timestamp, optional)"), + endDate: z + .number() + .optional() + .describe("Search end date (milliseconds timestamp, optional)"), + pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.extraBonusList({ + algo: params.algo, + userName: params.userName, + ...(params.coin && { coin: params.coin }), + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved extra bonuses related to mining activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved extra bonuses related to mining activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve extra bonuses related to mining activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve extra bonuses related to mining activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/hashrateResaleDetail.ts b/src/modules/mining/mining-api/hashrateResaleDetail.ts index fb286b2e..b83b271f 100644 --- a/src/modules/mining/mining-api/hashrateResaleDetail.ts +++ b/src/modules/mining/mining-api/hashrateResaleDetail.ts @@ -1,58 +1,75 @@ // src/tools/binance-mining/mining-api/hashrateResaleDetail.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleDetail(server: McpServer) { - server.tool( - "BinanceHashRateResaleDetail", + server.registerTool( + "BinanceHashRateResaleDetail", + { + description: "Retrieves details of hashrate resale transactions, including the transferring and receiving subaccounts, algorithm, hash rate, transfer date, and associated income.", - { - configId: z.number().int().min(1).describe("Mining ID"), - userName: z.string().min(1).describe("Mining Account"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleDetail({ - configId: params.configId, - userName: params.userName, - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + configId: z.number().int().min(1).describe("Mining ID"), + userName: z.string().min(1).describe("Mining Account"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const requestParams = { + configId: params.configId, + userName: params.userName, + ...(params.pageIndex != null && { pageIndex: params.pageIndex }), + ...(params.pageSize != null && { pageSize: params.pageSize }), + ...(params.recvWindow != null && { recvWindow: params.recvWindow }), + }; + const response = await ( + (miningClient as any).restAPI as { + hashrateResaleDetail: (p: any) => Promise<{ data: () => Promise }>; + } + ).hashrateResaleDetail(requestParams); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved details of hashrate resale transactions. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved details of hashrate resale transactions. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve details of hashrate resale transactions. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve details of hashrate resale transactions. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/hashrateResaleList.ts b/src/modules/mining/mining-api/hashrateResaleList.ts index 83ee293f..328fd0de 100644 --- a/src/modules/mining/mining-api/hashrateResaleList.ts +++ b/src/modules/mining/mining-api/hashrateResaleList.ts @@ -1,60 +1,70 @@ // src/tools/binance-mining/mining-api/hashrateResaleList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleList(server: McpServer) { - server.tool( - "BinanceHashRateResaleList", + server.registerTool( + "BinanceHashRateResaleList", + { + description: "Returns the list of hashRate resale configurations including transfer details such as algorithm, hashrate amount, sender and receiver pool usernames, start and end dates, and status of the transfer.", - { - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z - .number() - .int() - .min(10) - .max(200) - .optional() - .describe("Number of records per page, min 10, max 200"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleList({ - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of records per page, min 10, max 200"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.hashrateResaleList({ + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully return the list of hashRate resale configurations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully return the list of hashRate resale configurations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to return the list of hashRate resale configurations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to return the list of hashRate resale configurations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/hashrateResaleRequest.ts b/src/modules/mining/mining-api/hashrateResaleRequest.ts index 408caca8..6f81a5b4 100644 --- a/src/modules/mining/mining-api/hashrateResaleRequest.ts +++ b/src/modules/mining/mining-api/hashrateResaleRequest.ts @@ -1,60 +1,70 @@ // src/tools/binance-mining/mining-api/hashrateResaleRequest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleRequest(server: McpServer) { - server.tool( - "BinanceHashRateResaleRequest", + server.registerTool( + "BinanceHashRateResaleRequest", + { + description: "Retrieve a request for setting up a hashrate resale, specifying the mining account, algorithm, start and end times, target mining account for resale, and the amount of hashrate to transfer", - { - userName: z.string().min(1).describe("Mining Account"), - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - endDate: z.number().int().describe("Resale End Time (Millisecond timestamp)"), - startDate: z.number().int().describe("Resale Start Time (Millisecond timestamp)"), - toPoolUser: z.string().min(1).describe("Mining Account of the recipient pool user"), - hashRate: z - .number() - .int() - .describe("Resale hashrate h/s must be transferred (BTC > 500000000000, ETH > 500000)"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleRequest({ - userName: params.userName, - algo: params.algo, - endDate: params.endDate, - startDate: params.startDate, - toPoolUser: params.toPoolUser, - hashRate: params.hashRate, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + userName: z.string().min(1).describe("Mining Account"), + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + endDate: z.number().int().describe("Resale End Time (Millisecond timestamp)"), + startDate: z.number().int().describe("Resale Start Time (Millisecond timestamp)"), + toPoolUser: z.string().min(1).describe("Mining Account of the recipient pool user"), + hashRate: z + .number() + .int() + .describe("Resale hashrate h/s must be transferred (BTC > 500000000000, ETH > 500000)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.hashrateResaleRequest({ + userName: params.userName, + algo: params.algo, + endDate: params.endDate, + startDate: params.startDate, + toPoolUser: params.toPoolUser, + hashRate: params.hashRate, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved request for setting up a hashrate resale. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved request for setting up a hashrate resale. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve request for setting up a hashrate resale. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve request for setting up a hashrate resale. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/miningAccountEarning.ts b/src/modules/mining/mining-api/miningAccountEarning.ts index 09399b8b..0bd262c0 100644 --- a/src/modules/mining/mining-api/miningAccountEarning.ts +++ b/src/modules/mining/mining-api/miningAccountEarning.ts @@ -1,61 +1,67 @@ // src/tools/binance-mining/mining-api/miningAccountEarning.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceMiningAccountEarning(server: McpServer) { - server.tool( - "BinanceMiningAccountEarning", + server.registerTool( + "BinanceMiningAccountEarning", + { + description: "Retrieves the earnings associated with a mining account, including the type of earnings (e.g., rebate, referral, refund), sub-account ID, the mining account name, and the amount earned. It also supports pagination for large data sets.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - startDate: z.number().int().optional().describe("Millisecond timestamp for the start date"), - endDate: z.number().int().optional().describe("Millisecond timestamp for the end date"), - pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(10) - .max(200) - .optional() - .describe("Number of records per page, min 10, max 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.miningAccountEarning({ - algo: params.algo, - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + startDate: z.number().int().optional().describe("Millisecond timestamp for the start date"), + endDate: z.number().int().optional().describe("Millisecond timestamp for the end date"), + pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of records per page, min 10, max 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.miningAccountEarning({ + algo: params.algo, + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the earnings associated with a mining account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the earnings associated with a mining account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the earnings associated with a mining account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the earnings associated with a mining account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/requestForDetailMinerList.ts b/src/modules/mining/mining-api/requestForDetailMinerList.ts index df5fb763..3e2fde8b 100644 --- a/src/modules/mining/mining-api/requestForDetailMinerList.ts +++ b/src/modules/mining/mining-api/requestForDetailMinerList.ts @@ -1,51 +1,57 @@ // src/tools/binance-mining/mining-api/requestForDetailMinerList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceRequestForDetailMinerList(server: McpServer) { - server.tool( - "BinanceRequestForDetailMinerList", + server.registerTool( + "BinanceRequestForDetailMinerList", + { + description: "Retrieves detailed hashrate data for a specific miner, including both hourly (H_hashrate) and daily (D_hashrate) metrics such as time, hashrate, and rejection rate.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - workerName: z.string().min(1).describe("Miner’s name (required), e.g., bhdc1.16A10404B"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.requestForDetailMinerList({ - algo: params.algo, - userName: params.userName, - workerName: params.workerName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + workerName: z.string().min(1).describe("Miner’s name (required), e.g., bhdc1.16A10404B"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.requestForDetailMinerList({ + algo: params.algo, + userName: params.userName, + workerName: params.workerName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved detailed hashrate data for a specific miner. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved detailed hashrate data for a specific miner. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve detailed hashrate data for a specific miner. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve detailed hashrate data for a specific miner. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/requestForMinerList.ts b/src/modules/mining/mining-api/requestForMinerList.ts index 009f3811..8385bacb 100644 --- a/src/modules/mining/mining-api/requestForMinerList.ts +++ b/src/modules/mining/mining-api/requestForMinerList.ts @@ -1,82 +1,88 @@ // src/tools/binance-mining/mining-api/requestForMinerList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceRequestForMinerList(server: McpServer) { - server.tool( - "BinanceRequestForMinerList", + server.registerTool( + "BinanceRequestForMinerList", + { + description: "Retrieves a list of miners (workers) associated with a mining account, including details such as miner name, status, real-time hashrate, 24H hashrate, rejection rate, and last submission time.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is first page, starting from 1"), - sort: z - .number() - .int() - .min(0) - .max(1) - .optional() - .describe("Sort sequence: 0 = ascending (default), 1 = descending"), - sortColumn: z - .number() - .int() - .min(1) - .max(5) - .optional() - .describe( - `Sort by (default = 1): 1: miner name, 2: real-time computing power, 3: daily average computing power, 4: real-time rejection rate, 5: last submission time` - ), - workerStatus: z - .number() - .int() - .min(0) - .max(3) - .optional() - .describe("Miner status (default = 0): 0 = all, 1 = valid, 2 = invalid, 3 = failure"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.requestForMinerList({ - algo: params.algo, - userName: params.userName, - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.sort && { sort: params.sort }), - ...(params.sortColumn && { sortColumn: params.sortColumn }), - ...(params.workerStatus && { workerStatus: params.workerStatus }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is first page, starting from 1"), + sort: z + .number() + .int() + .min(0) + .max(1) + .optional() + .describe("Sort sequence: 0 = ascending (default), 1 = descending"), + sortColumn: z + .number() + .int() + .min(1) + .max(5) + .optional() + .describe( + `Sort by (default = 1): 1: miner name, 2: real-time computing power, 3: daily average computing power, 4: real-time rejection rate, 5: last submission time`, + ), + workerStatus: z + .number() + .int() + .min(0) + .max(3) + .optional() + .describe("Miner status (default = 0): 0 = all, 1 = valid, 2 = invalid, 3 = failure"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.requestForMinerList({ + algo: params.algo, + userName: params.userName, + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.sort && { sort: params.sort }), + ...(params.sortColumn && { sortColumn: params.sortColumn }), + ...(params.workerStatus && { workerStatus: params.workerStatus }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved a list of miners (workers) associated with a mining account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved a list of miners (workers) associated with a mining account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of miners (workers) associated with a mining account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of miners (workers) associated with a mining account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/mining/mining-api/statisticList.ts b/src/modules/mining/mining-api/statisticList.ts index 3be2a279..187bbde7 100644 --- a/src/modules/mining/mining-api/statisticList.ts +++ b/src/modules/mining/mining-api/statisticList.ts @@ -1,48 +1,58 @@ // src/tools/binance-mining/mining-api/statisticList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceStatisticList(server: McpServer) { - server.tool( - "BinanceStatisticList", + server.registerTool( + "BinanceStatisticList", + { + description: "Retrieve mining statistics for a specific account, including hash rates for the past 15 minutes and 24 hours, the number of valid and invalid mining units, and the estimated profit for today and yesterday in various cryptocurrencies.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.statisticList({ - algo: params.algo, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.statisticList({ + algo: params.algo, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved mining statistics for a specific account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved mining statistics for a specific account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve mining statistics for a specific account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve mining statistics for a specific account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/nft/index.ts b/src/modules/nft/index.ts index 949f44e2..40ca3a2e 100644 --- a/src/modules/nft/index.ts +++ b/src/modules/nft/index.ts @@ -1,15 +1,16 @@ // src/tools/binance-fiat/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceGetNFTAsset } from "./nft-api/getNFTAsset.js"; import { registerBinanceGetNFTDepositHistory } from "./nft-api/getNFTDepositHistory.js"; -import { registerBinanceGetNFTWithdrawHistory } from "./nft-api/getNFTWithdrawHistory.js"; import { registerBinanceGetNFTTransactionHistory } from "./nft-api/getNFTTransactionHistory.js"; -import { registerBinanceGetNFTAsset } from "./nft-api/getNFTAsset.js"; +import { registerBinanceGetNFTWithdrawHistory } from "./nft-api/getNFTWithdrawHistory.js"; export function registerBinanceNFTTools(server: McpServer) { - registerBinanceGetNFTDepositHistory(server); - registerBinanceGetNFTWithdrawHistory(server); - registerBinanceGetNFTTransactionHistory(server); - registerBinanceGetNFTAsset(server); + registerBinanceGetNFTDepositHistory(server); + registerBinanceGetNFTWithdrawHistory(server); + registerBinanceGetNFTTransactionHistory(server); + registerBinanceGetNFTAsset(server); } // Alias for binance.ts compatibility diff --git a/src/modules/nft/nft-api/getNFTAsset.ts b/src/modules/nft/nft-api/getNFTAsset.ts index e5d658b0..028b6474 100644 --- a/src/modules/nft/nft-api/getNFTAsset.ts +++ b/src/modules/nft/nft-api/getNFTAsset.ts @@ -1,54 +1,64 @@ // src/tools/binance-nft/nft-api/getNFTAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTAsset(server: McpServer) { - server.tool( - "BinanceGetNFTAsset", + server.registerTool( + "BinanceGetNFTAsset", + { + description: "Retrieve NFT assets associated with a user's account. It returns details about the network, contract address, and token IDs for each NFT asset.", - { - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTAsset({ - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTAsset({ + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT assets associated with a user's account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT assets associated with a user's account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT assets : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT assets : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/nft/nft-api/getNFTDepositHistory.ts b/src/modules/nft/nft-api/getNFTDepositHistory.ts index 631e647c..41a7ab5a 100644 --- a/src/modules/nft/nft-api/getNFTDepositHistory.ts +++ b/src/modules/nft/nft-api/getNFTDepositHistory.ts @@ -1,58 +1,68 @@ // src/tools/binance-nft/nft-api/getNFTDepositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTDepositHistory(server: McpServer) { - server.tool( - "BinanceGetNFTDepositHistory", + server.registerTool( + "BinanceGetNFTDepositHistory", + { + description: "Retrieves NFT deposit history, including network, contract address, token ID, transaction ID (if available), and timestamps.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .optional() - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().optional().describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTDepositHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .optional() + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().optional().describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTDepositHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT deposit history, including network, contract address, token ID. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT deposit history, including network, contract address, token ID. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieves NFT deposit history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieves NFT deposit history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/nft/nft-api/getNFTTransactionHistory.ts b/src/modules/nft/nft-api/getNFTTransactionHistory.ts index 86b27c9f..ecbbc676 100644 --- a/src/modules/nft/nft-api/getNFTTransactionHistory.ts +++ b/src/modules/nft/nft-api/getNFTTransactionHistory.ts @@ -1,62 +1,72 @@ // src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTTransactionHistory(server: McpServer) { - server.tool( - "BinanceGetNFTTransactionHistory", + server.registerTool( + "BinanceGetNFTTransactionHistory", + { + description: "Retrieves NFT transaction history, including purchase orders, sale orders, royalty income, primary market orders, and mint fees. It returns details about the NFT network, token IDs, contract addresses, transaction times, trade amounts, and the currencies used in the transactions.", - { - orderType: z - .number() - .describe( - "Order type: 0 for purchase order, 1 for sell order, 2 for royalty income, 3 for primary market order, 4 for mint fee" - ), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTTransactionHistory({ - orderType: params.orderType, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderType: z + .number() + .describe( + "Order type: 0 for purchase order, 1 for sell order, 2 for royalty income, 3 for primary market order, 4 for mint fee", + ), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTTransactionHistory({ + orderType: params.orderType, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT transaction history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT transaction history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT transaction history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT transaction history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/nft/nft-api/getNFTWithdrawHistory.ts b/src/modules/nft/nft-api/getNFTWithdrawHistory.ts index f2ab7722..924599a8 100644 --- a/src/modules/nft/nft-api/getNFTWithdrawHistory.ts +++ b/src/modules/nft/nft-api/getNFTWithdrawHistory.ts @@ -1,58 +1,68 @@ // src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTWithdrawHistory(server: McpServer) { - server.tool( - "BinanceGetNFTWithdrawHistory", + server.registerTool( + "BinanceGetNFTWithdrawHistory", + { + description: "Retrieves NFT withdraw history, including network, transaction ID, contract address, token ID, withdrawal fee, fee asset, and timestamps.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTWithdrawHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTWithdrawHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT withdraw history, including network, transaction ID, contract address. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT withdraw history, including network, transaction ID, contract address. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT withdraw history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT withdraw history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/getAccount.ts b/src/modules/options/account-api/getAccount.ts index 3fc5e4f0..504c6095 100644 --- a/src/modules/options/account-api/getAccount.ts +++ b/src/modules/options/account-api/getAccount.ts @@ -5,60 +5,67 @@ * @license Apache-2.0 */ // src/modules/options/account-api/getAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetAccount(server: McpServer) { - server.tool( - "BinanceOptionsGetAccount", - "Get options account information including balances and Greeks.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.account({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Account Information\n\n`; - - if (data) { - result += `**Account Details**\n`; - result += `Asset: ${data.asset}\n`; - result += `Margin Balance: ${data.marginBalance}\n`; - result += `Equity: ${data.equity}\n`; - result += `Available: ${data.available}\n`; - result += `Unrealized PnL: ${data.unrealizedPNL}\n`; - result += `Maintenance Margin: ${data.maintenanceMargin}\n`; - result += `Initial Margin: ${data.initialMargin}\n\n`; - - result += `**Greeks**\n`; - result += `Delta: ${data.delta || 'N/A'}\n`; - result += `Theta: ${data.theta || 'N/A'}\n`; - result += `Gamma: ${data.gamma || 'N/A'}\n`; - result += `Vega: ${data.vega || 'N/A'}\n`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options account: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsGetAccount", + { + description: "Get options account information including balances and Greeks.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.account({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Account Information\n\n`; + + if (data) { + result += `**Account Details**\n`; + result += `Asset: ${data.asset}\n`; + result += `Margin Balance: ${data.marginBalance}\n`; + result += `Equity: ${data.equity}\n`; + result += `Available: ${data.available}\n`; + result += `Unrealized PnL: ${data.unrealizedPNL}\n`; + result += `Maintenance Margin: ${data.maintenanceMargin}\n`; + result += `Initial Margin: ${data.initialMargin}\n\n`; + + result += `**Greeks**\n`; + result += `Delta: ${data.delta || "N/A"}\n`; + result += `Theta: ${data.theta || "N/A"}\n`; + result += `Gamma: ${data.gamma || "N/A"}\n`; + result += `Vega: ${data.vega || "N/A"}\n`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options account: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/getBillHistory.ts b/src/modules/options/account-api/getBillHistory.ts index 1eff6bb5..7c6b9722 100644 --- a/src/modules/options/account-api/getBillHistory.ts +++ b/src/modules/options/account-api/getBillHistory.ts @@ -5,70 +5,84 @@ * @license Apache-2.0 */ // src/modules/options/account-api/getBillHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetBillHistory(server: McpServer) { - server.tool( - "BinanceOptionsGetBillHistory", + server.registerTool( + "BinanceOptionsGetBillHistory", + { + description: "Get options account funding flow (bill history). Shows transfers, fees, PnL, and other account activities.", - { - currency: z.string().describe("Currency (e.g., 'USDT')"), - recordId: z.number().int().optional().describe("Record ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of records to return (default 100, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.bill({ - currency: params.currency, - ...(params.recordId && { recordId: params.recordId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Bill History\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total records: ${data.length}\n\n`; - data.slice(0, 20).forEach((record: any, index: number) => { - result += `**${index + 1}. ${record.type}**\n`; - result += ` ID: ${record.id}\n`; - result += ` Amount: ${record.amount} ${record.currency}\n`; - result += ` Balance: ${record.balance}\n`; - if (record.symbol) result += ` Symbol: ${record.symbol}\n`; - result += ` Time: ${new Date(record.createTime).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more records`; - } - } else { - result += `No bill history found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options bill history: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + currency: z.string().describe("Currency (e.g., 'USDT')"), + recordId: z.number().int().optional().describe("Record ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of records to return (default 100, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.bill({ + currency: params.currency, + ...(params.recordId && { recordId: params.recordId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Bill History\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total records: ${data.length}\n\n`; + data.slice(0, 20).forEach((record: any, index: number) => { + result += `**${index + 1}. ${record.type}**\n`; + result += ` ID: ${record.id}\n`; + result += ` Amount: ${record.amount} ${record.currency}\n`; + result += ` Balance: ${record.balance}\n`; + if (record.symbol) result += ` Symbol: ${record.symbol}\n`; + result += ` Time: ${new Date(record.createTime).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more records`; + } + } else { + result += `No bill history found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options bill history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/getIncomeAsyn.ts b/src/modules/options/account-api/getIncomeAsyn.ts index 1552198b..3c9eef90 100644 --- a/src/modules/options/account-api/getIncomeAsyn.ts +++ b/src/modules/options/account-api/getIncomeAsyn.ts @@ -5,45 +5,53 @@ * @license Apache-2.0 */ // src/modules/options/account-api/getIncomeAsyn.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetIncomeAsyn(server: McpServer) { - server.tool( - "BinanceOptionsGetIncomeAsyn", + server.registerTool( + "BinanceOptionsGetIncomeAsyn", + { + description: "Request to generate an async download ID for options income history. Use with BinanceOptionsGetIncomeAsynId to retrieve results.", - { - startTime: z.number().int().describe("Start time in milliseconds"), - endTime: z.number().int().describe("End time in milliseconds"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.incomeAsyn({ - startTime: params.startTime, - endTime: params.endTime, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options Income Download Request Submitted\n\nDownload ID: ${data.downloadId || data.id}\n\nUse BinanceOptionsGetIncomeAsynId with this ID to retrieve the download URL.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to request options income download: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + startTime: z.number().int().describe("Start time in milliseconds"), + endTime: z.number().int().describe("End time in milliseconds"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.incomeAsyn({ + startTime: params.startTime, + endTime: params.endTime, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `✅ Options Income Download Request Submitted\n\nDownload ID: ${data.downloadId || data.id}\n\nUse BinanceOptionsGetIncomeAsynId with this ID to retrieve the download URL.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to request options income download: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/getIncomeAsynId.ts b/src/modules/options/account-api/getIncomeAsynId.ts index 3f6e9e19..5d0ff07e 100644 --- a/src/modules/options/account-api/getIncomeAsynId.ts +++ b/src/modules/options/account-api/getIncomeAsynId.ts @@ -5,54 +5,62 @@ * @license Apache-2.0 */ // src/modules/options/account-api/getIncomeAsynId.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetIncomeAsynId(server: McpServer) { - server.tool( - "BinanceOptionsGetIncomeAsynId", + server.registerTool( + "BinanceOptionsGetIncomeAsynId", + { + description: "Get the download URL for options income history using a download ID from BinanceOptionsGetIncomeAsyn.", - { - downloadId: z.string().describe("Download ID from BinanceOptionsGetIncomeAsyn"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.incomeAsynId({ - downloadId: params.downloadId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Income Download Status\n\n`; - result += `Download ID: ${params.downloadId}\n`; - result += `Status: ${data.status}\n`; - - if (data.url) { - result += `\n**Download URL**: ${data.url}\n`; - result += `\nNote: URL is valid for a limited time.`; - } else if (data.status === 'processing') { - result += `\nThe download is still being processed. Please try again in a few moments.`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options income download: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + downloadId: z.string().describe("Download ID from BinanceOptionsGetIncomeAsyn"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.incomeAsynId({ + downloadId: params.downloadId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Income Download Status\n\n`; + result += `Download ID: ${params.downloadId}\n`; + result += `Status: ${data.status}\n`; + + if (data.url) { + result += `\n**Download URL**: ${data.url}\n`; + result += `\nNote: URL is valid for a limited time.`; + } else if (data.status === "processing") { + result += `\nThe download is still being processed. Please try again in a few moments.`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options income download: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/getPosition.ts b/src/modules/options/account-api/getPosition.ts index 9d10a360..4c61b4b1 100644 --- a/src/modules/options/account-api/getPosition.ts +++ b/src/modules/options/account-api/getPosition.ts @@ -5,63 +5,73 @@ * @license Apache-2.0 */ // src/modules/options/account-api/getPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetPosition(server: McpServer) { - server.tool( - "BinanceOptionsGetPosition", - "Get current options positions. Shows all active option contracts held.", - { - symbol: z.string().optional().describe("Option symbol to filter by"), - underlying: z.string().optional().describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.position({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.underlying && { underlying: params.underlying }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Positions\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total positions: ${data.length}\n\n`; - data.forEach((pos: any, index: number) => { - result += `**${index + 1}. ${pos.symbol}**\n`; - result += ` Side: ${pos.side}\n`; - result += ` Quantity: ${pos.quantity}\n`; - result += ` Entry Price: ${pos.entryPrice}\n`; - result += ` Mark Price: ${pos.markPrice}\n`; - result += ` Unrealized PnL: ${pos.unrealizedPNL}\n`; - result += ` Maintenance Margin: ${pos.maintMargin}\n`; - result += ` Expiry Date: ${pos.expiryDate}\n\n`; - }); - } else { - result += `No positions found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options positions: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsGetPosition", + { + description: "Get current options positions. Shows all active option contracts held.", + inputSchema: { + symbol: z.string().optional().describe("Option symbol to filter by"), + underlying: z + .string() + .optional() + .describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.position({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.underlying && { underlying: params.underlying }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Positions\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total positions: ${data.length}\n\n`; + data.forEach((pos: any, index: number) => { + result += `**${index + 1}. ${pos.symbol}**\n`; + result += ` Side: ${pos.side}\n`; + result += ` Quantity: ${pos.quantity}\n`; + result += ` Entry Price: ${pos.entryPrice}\n`; + result += ` Mark Price: ${pos.markPrice}\n`; + result += ` Unrealized PnL: ${pos.unrealizedPNL}\n`; + result += ` Maintenance Margin: ${pos.maintMargin}\n`; + result += ` Expiry Date: ${pos.expiryDate}\n\n`; + }); + } else { + result += `No positions found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/account-api/index.ts b/src/modules/options/account-api/index.ts index 1a2485fe..2f9dfaac 100644 --- a/src/modules/options/account-api/index.ts +++ b/src/modules/options/account-api/index.ts @@ -5,17 +5,18 @@ * @license Apache-2.0 */ // src/modules/options/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerOptionsGetAccount } from "./getAccount.js"; -import { registerOptionsGetPosition } from "./getPosition.js"; import { registerOptionsGetBillHistory } from "./getBillHistory.js"; import { registerOptionsGetIncomeAsyn } from "./getIncomeAsyn.js"; import { registerOptionsGetIncomeAsynId } from "./getIncomeAsynId.js"; +import { registerOptionsGetPosition } from "./getPosition.js"; export function registerOptionsAccountApi(server: McpServer) { - registerOptionsGetAccount(server); - registerOptionsGetPosition(server); - registerOptionsGetBillHistory(server); - registerOptionsGetIncomeAsyn(server); - registerOptionsGetIncomeAsynId(server); + registerOptionsGetAccount(server); + registerOptionsGetPosition(server); + registerOptionsGetBillHistory(server); + registerOptionsGetIncomeAsyn(server); + registerOptionsGetIncomeAsynId(server); } diff --git a/src/modules/options/index.ts b/src/modules/options/index.ts index 255719b1..664cdfe9 100644 --- a/src/modules/options/index.ts +++ b/src/modules/options/index.ts @@ -1,7 +1,8 @@ // src/modules/options/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceOptionsTools } from "../../tools/binance-options/index.js"; export function registerOptions(server: McpServer) { - registerBinanceOptionsTools(server); + registerBinanceOptionsTools(server); } diff --git a/src/modules/options/market-api/depth.ts b/src/modules/options/market-api/depth.ts index 7fa55c34..31da2b9a 100644 --- a/src/modules/options/market-api/depth.ts +++ b/src/modules/options/market-api/depth.ts @@ -5,65 +5,78 @@ * @license Apache-2.0 */ // src/modules/options/market-api/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketDepth(server: McpServer) { - server.tool( - "BinanceOptionsDepth", + server.registerTool( + "BinanceOptionsDepth", + { + description: "Get the order book depth for an options contract. Shows current bids and asks at various price levels.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - limit: z.number().int().min(1).max(1000).optional() - .describe("Limit the number of price levels returned (default 100, max 1000)") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.depth({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - let result = `✅ Options Order Book - ${params.symbol}\n\n`; - - // Format asks (sell orders) - result += `**Asks (Sell Orders)**:\n`; - if (data.asks && data.asks.length > 0) { - data.asks.slice(0, 10).forEach((ask: [string, string]) => { - result += ` Price: ${ask[0]} | Qty: ${ask[1]}\n`; - }); - } else { - result += ` No asks available\n`; - } - - result += `\n**Bids (Buy Orders)**:\n`; - if (data.bids && data.bids.length > 0) { - data.bids.slice(0, 10).forEach((bid: [string, string]) => { - result += ` Price: ${bid[0]} | Qty: ${bid[1]}\n`; - }); - } else { - result += ` No bids available\n`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options order book: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Limit the number of price levels returned (default 100, max 1000)"), + }, + }, + async (params) => { + try { + const data = await optionsClient.depth({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + + let result = `✅ Options Order Book - ${params.symbol}\n\n`; + + // Format asks (sell orders) + result += `**Asks (Sell Orders)**:\n`; + if (data.asks && data.asks.length > 0) { + data.asks.slice(0, 10).forEach((ask: [string, string]) => { + result += ` Price: ${ask[0]} | Qty: ${ask[1]}\n`; + }); + } else { + result += ` No asks available\n`; + } + + result += `\n**Bids (Buy Orders)**:\n`; + if (data.bids && data.bids.length > 0) { + data.bids.slice(0, 10).forEach((bid: [string, string]) => { + result += ` Price: ${bid[0]} | Qty: ${bid[1]}\n`; + }); + } else { + result += ` No bids available\n`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options order book: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/exchangeInfo.ts b/src/modules/options/market-api/exchangeInfo.ts index 54597549..d64b66d5 100644 --- a/src/modules/options/market-api/exchangeInfo.ts +++ b/src/modules/options/market-api/exchangeInfo.ts @@ -5,57 +5,64 @@ * @license Apache-2.0 */ // src/modules/options/market-api/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../../config/binanceClient.js"; export function registerOptionsMarketExchangeInfo(server: McpServer) { - server.tool( - "BinanceOptionsExchangeInfo", + server.registerTool( + "BinanceOptionsExchangeInfo", + { + description: "Get current exchange trading rules and symbol information for options. Returns available option contracts, trading pairs, and their specifications.", - {}, - async () => { - try { - const response = await optionsClient.restAPI.exchangeInfo(); - const data = await response.data(); - - // Summarize the response - const optionSymbols = data.optionSymbols || []; - const assets = data.optionAssets || []; - - let summary = `✅ Options Exchange Information\n\n`; - summary += `**Timezone**: ${data.timezone}\n`; - summary += `**Server Time**: ${new Date(data.serverTime).toISOString()}\n\n`; - summary += `**Available Assets**: ${assets.length}\n`; - summary += `**Option Contracts**: ${optionSymbols.length}\n\n`; - - if (assets.length > 0) { - summary += `**Assets**: ${assets.map((a: any) => a.name || a).join(', ')}\n\n`; - } - - // Show first few contracts as examples - if (optionSymbols.length > 0) { - summary += `**Sample Contracts** (first 5):\n`; - optionSymbols.slice(0, 5).forEach((sym: any) => { - summary += `- ${sym.symbol}: ${sym.underlying} ${sym.side} Strike: ${sym.strikePrice} Expiry: ${sym.expiryDate}\n`; - }); - } - - return { - content: [{ - type: "text", - text: summary - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options exchange info: ${errorMessage}` - }], - isError: true - }; - } + }, + async () => { + try { + const data = await optionsClient.exchangeInfo(); + + // Summarize the response + const optionSymbols = data.optionSymbols || []; + const assets = data.optionAssets || []; + + let summary = `✅ Options Exchange Information\n\n`; + summary += `**Timezone**: ${data.timezone}\n`; + summary += `**Server Time**: ${new Date(data.serverTime).toISOString()}\n\n`; + summary += `**Available Assets**: ${assets.length}\n`; + summary += `**Option Contracts**: ${optionSymbols.length}\n\n`; + + if (assets.length > 0) { + summary += `**Assets**: ${assets.map((a: any) => a.name || a).join(", ")}\n\n`; } - ); + + // Show first few contracts as examples + if (optionSymbols.length > 0) { + summary += `**Sample Contracts** (first 5):\n`; + optionSymbols.slice(0, 5).forEach((sym: any) => { + summary += `- ${sym.symbol}: ${sym.underlying} ${sym.side} Strike: ${sym.strikePrice} Expiry: ${sym.expiryDate}\n`; + }); + } + + return { + content: [ + { + type: "text", + text: summary, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options exchange info: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/exerciseHistory.ts b/src/modules/options/market-api/exerciseHistory.ts index 92312ceb..abf4475c 100644 --- a/src/modules/options/market-api/exerciseHistory.ts +++ b/src/modules/options/market-api/exerciseHistory.ts @@ -5,67 +5,77 @@ * @license Apache-2.0 */ // src/modules/options/market-api/exerciseHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketExerciseHistory(server: McpServer) { - server.tool( - "BinanceOptionsExerciseHistory", + server.registerTool( + "BinanceOptionsExerciseHistory", + { + description: "Get the exercise history for options contracts. Shows historical exercise records and settlement prices.", - { - underlying: z.string().optional() - .describe("Underlying asset (e.g., 'BTCUSDT')"), - startTime: z.number().int().optional() - .describe("Start time in milliseconds"), - endTime: z.number().int().optional() - .describe("End time in milliseconds"), - limit: z.number().int().min(1).max(100).optional() - .describe("Number of records to return (default 100, max 100)") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.exerciseHistory({ - ...(params.underlying && { underlying: params.underlying }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - let result = `✅ Options Exercise History\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total records: ${data.length}\n\n`; - data.forEach((record: any) => { - const exerciseTime = new Date(record.expiryDate).toISOString(); - result += `**${record.symbol}**\n`; - result += ` Strike Price: ${record.strikePrice}\n`; - result += ` Real Strike Price: ${record.realStrikePrice}\n`; - result += ` Exercise Price: ${record.exercisePrice}\n`; - result += ` Expiry Date: ${exerciseTime}\n\n`; - }); - } else { - result += `No exercise history found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options exercise history: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + underlying: z.string().optional().describe("Underlying asset (e.g., 'BTCUSDT')"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of records to return (default 100, max 100)"), + }, + }, + async (params) => { + try { + const data = await optionsClient.exerciseRecord({ + ...(params.underlying && { underlying: params.underlying }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + let result = `✅ Options Exercise History\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total records: ${data.length}\n\n`; + data.forEach((record: any) => { + const exerciseTime = new Date(record.expiryDate).toISOString(); + result += `**${record.symbol}**\n`; + result += ` Strike Price: ${record.strikePrice}\n`; + result += ` Real Strike Price: ${record.realStrikePrice}\n`; + result += ` Exercise Price: ${record.exercisePrice}\n`; + result += ` Expiry Date: ${exerciseTime}\n\n`; + }); + } else { + result += `No exercise history found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options exercise history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/historicalTrades.ts b/src/modules/options/market-api/historicalTrades.ts index 91725fb7..aa9ffc5c 100644 --- a/src/modules/options/market-api/historicalTrades.ts +++ b/src/modules/options/market-api/historicalTrades.ts @@ -5,62 +5,77 @@ * @license Apache-2.0 */ // src/modules/options/market-api/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketHistoricalTrades(server: McpServer) { - server.tool( - "BinanceOptionsHistoricalTrades", - "Get older market trades for an options contract. Requires API key.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - limit: z.number().int().min(1).max(500).optional() - .describe("Number of trades to return (default 100, max 500)"), - fromId: z.number().int().optional() - .describe("Trade ID to fetch from. Default gets most recent trades") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.historicalTrades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }), - ...(params.fromId && { fromId: params.fromId }) - }); - - const data = await response.data(); - - let result = `✅ Historical Trades - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades returned: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - const time = new Date(trade.time).toISOString(); - result += `${index + 1}. ID: ${trade.id} | Price: ${trade.price} | Qty: ${trade.qty} | Time: ${time}\n`; - }); - if (data.length > 20) { - result += `\n... and ${data.length - 20} more trades`; - } - } else { - result += `No historical trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options historical trades: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsHistoricalTrades", + { + description: "Get older market trades for an options contract. Requires API key.", + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + limit: z + .number() + .int() + .min(1) + .max(500) + .optional() + .describe("Number of trades to return (default 100, max 500)"), + fromId: z + .number() + .int() + .optional() + .describe("Trade ID to fetch from. Default gets most recent trades"), + }, + }, + async (params) => { + try { + const data = await optionsClient.historicalTrades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + ...(params.fromId && { fromId: params.fromId }), + }); + + let result = `✅ Historical Trades - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades returned: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + const time = new Date(trade.time).toISOString(); + result += `${index + 1}. ID: ${trade.id} | Price: ${trade.price} | Qty: ${trade.qty} | Time: ${time}\n`; + }); + if (data.length > 20) { + result += `\n... and ${data.length - 20} more trades`; + } + } else { + result += `No historical trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options historical trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/index.ts b/src/modules/options/market-api/index.ts index f70eef80..e93f287d 100644 --- a/src/modules/options/market-api/index.ts +++ b/src/modules/options/market-api/index.ts @@ -5,29 +5,30 @@ * @license Apache-2.0 */ // src/modules/options/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerOptionsMarketPing } from "./ping.js"; -import { registerOptionsMarketTime } from "./time.js"; -import { registerOptionsMarketExchangeInfo } from "./exchangeInfo.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerOptionsMarketDepth } from "./depth.js"; -import { registerOptionsMarketTrades } from "./trades.js"; +import { registerOptionsMarketExchangeInfo } from "./exchangeInfo.js"; +import { registerOptionsMarketExerciseHistory } from "./exerciseHistory.js"; import { registerOptionsMarketHistoricalTrades } from "./historicalTrades.js"; +import { registerOptionsMarketIndex } from "./indexPrice.js"; import { registerOptionsMarketKlines } from "./klines.js"; import { registerOptionsMarketMark } from "./mark.js"; +import { registerOptionsMarketPing } from "./ping.js"; import { registerOptionsMarketTicker } from "./ticker.js"; -import { registerOptionsMarketIndex } from "./indexPrice.js"; -import { registerOptionsMarketExerciseHistory } from "./exerciseHistory.js"; +import { registerOptionsMarketTime } from "./time.js"; +import { registerOptionsMarketTrades } from "./trades.js"; export function registerOptionsMarketApi(server: McpServer) { - registerOptionsMarketPing(server); - registerOptionsMarketTime(server); - registerOptionsMarketExchangeInfo(server); - registerOptionsMarketDepth(server); - registerOptionsMarketTrades(server); - registerOptionsMarketHistoricalTrades(server); - registerOptionsMarketKlines(server); - registerOptionsMarketMark(server); - registerOptionsMarketTicker(server); - registerOptionsMarketIndex(server); - registerOptionsMarketExerciseHistory(server); + registerOptionsMarketPing(server); + registerOptionsMarketTime(server); + registerOptionsMarketExchangeInfo(server); + registerOptionsMarketDepth(server); + registerOptionsMarketTrades(server); + registerOptionsMarketHistoricalTrades(server); + registerOptionsMarketKlines(server); + registerOptionsMarketMark(server); + registerOptionsMarketTicker(server); + registerOptionsMarketIndex(server); + registerOptionsMarketExerciseHistory(server); } diff --git a/src/modules/options/market-api/indexPrice.ts b/src/modules/options/market-api/indexPrice.ts index 5e74f6f4..39d1e38c 100644 --- a/src/modules/options/market-api/indexPrice.ts +++ b/src/modules/options/market-api/indexPrice.ts @@ -5,60 +5,68 @@ * @license Apache-2.0 */ // src/modules/options/market-api/indexPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketIndex(server: McpServer) { - server.tool( - "BinanceOptionsIndex", + server.registerTool( + "BinanceOptionsIndex", + { + description: "Get the current index price for the underlying asset. The index price is used as a reference for options pricing.", - { - underlying: z.string().describe("Underlying asset (e.g., 'BTCUSDT', 'ETHUSDT')") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.index({ - underlying: params.underlying - }); - - const data = await response.data(); - - let result = `✅ Options Index Price\n\n`; - - if (Array.isArray(data)) { - data.forEach((item: any) => { - result += `**${item.underlying || item.indexSymbol}**\n`; - result += `Index Price: ${item.indexPrice}\n`; - if (item.time) { - result += `Time: ${new Date(item.time).toISOString()}\n`; - } - result += '\n'; - }); - } else if (data) { - result += `**${data.underlying || data.indexSymbol || params.underlying}**\n`; - result += `Index Price: ${data.indexPrice}\n`; - if (data.time) { - result += `Time: ${new Date(data.time).toISOString()}\n`; - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options index price: ${errorMessage}` - }], - isError: true - }; + inputSchema: { + underlying: z.string().describe("Underlying asset (e.g., 'BTCUSDT', 'ETHUSDT')"), + }, + }, + async (params) => { + try { + const data = await optionsClient.index({ + underlying: params.underlying, + }); + + let result = `✅ Options Index Price\n\n`; + + if (Array.isArray(data)) { + data.forEach((item: any) => { + result += `**${item.underlying || item.indexSymbol}**\n`; + result += `Index Price: ${item.indexPrice}\n`; + if (item.time) { + result += `Time: ${new Date(item.time).toISOString()}\n`; } + result += "\n"; + }); + } else if (data) { + result += `**${data.underlying || data.indexSymbol || params.underlying}**\n`; + result += `Index Price: ${data.indexPrice}\n`; + if (data.time) { + result += `Time: ${new Date(data.time).toISOString()}\n`; + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options index price: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/klines.ts b/src/modules/options/market-api/klines.ts index a63d7053..f3a590aa 100644 --- a/src/modules/options/market-api/klines.ts +++ b/src/modules/options/market-api/klines.ts @@ -5,72 +5,84 @@ * @license Apache-2.0 */ // src/modules/options/market-api/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketKlines(server: McpServer) { - server.tool( - "BinanceOptionsKlines", + server.registerTool( + "BinanceOptionsKlines", + { + description: "Get kline/candlestick data for an options contract. Returns OHLCV data for technical analysis.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - interval: z.enum(["1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d", "3d", "1w"]) - .describe("Kline interval"), - startTime: z.number().int().optional() - .describe("Start time in milliseconds"), - endTime: z.number().int().optional() - .describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1500).optional() - .describe("Number of klines to return (default 500, max 1500)") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.klines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - let result = `✅ Klines - ${params.symbol} (${params.interval})\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total candles: ${data.length}\n\n`; - result += `| Open Time | Open | High | Low | Close | Volume |\n`; - result += `|-----------|------|------|-----|-------|--------|\n`; - - data.slice(-10).forEach((kline: any) => { - const openTime = new Date(kline[0]).toISOString().slice(0, 16); - result += `| ${openTime} | ${kline[1]} | ${kline[2]} | ${kline[3]} | ${kline[4]} | ${kline[5]} |\n`; - }); - - if (data.length > 10) { - result += `\nShowing last 10 of ${data.length} candles`; - } - } else { - result += `No kline data found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options klines: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + interval: z + .enum(["1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d", "3d", "1w"]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1500) + .optional() + .describe("Number of klines to return (default 500, max 1500)"), + }, + }, + async (params) => { + try { + const data = await optionsClient.klines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + let result = `✅ Klines - ${params.symbol} (${params.interval})\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total candles: ${data.length}\n\n`; + result += `| Open Time | Open | High | Low | Close | Volume |\n`; + result += `|-----------|------|------|-----|-------|--------|\n`; + + data.slice(-10).forEach((kline: any) => { + const openTime = new Date(kline[0]).toISOString().slice(0, 16); + result += `| ${openTime} | ${kline[1]} | ${kline[2]} | ${kline[3]} | ${kline[4]} | ${kline[5]} |\n`; + }); + + if (data.length > 10) { + result += `\nShowing last 10 of ${data.length} candles`; + } + } else { + result += `No kline data found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/mark.ts b/src/modules/options/market-api/mark.ts index f929ffb1..2822bf85 100644 --- a/src/modules/options/market-api/mark.ts +++ b/src/modules/options/market-api/mark.ts @@ -5,66 +5,78 @@ * @license Apache-2.0 */ // src/modules/options/market-api/mark.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketMark(server: McpServer) { - server.tool( - "BinanceOptionsMark", + server.registerTool( + "BinanceOptionsMark", + { + description: "Get the mark price for options contracts. Mark price is used for liquidation and margin calculations.", - { - symbol: z.string().optional() - .describe("Option symbol (e.g., 'BTC-240126-40000-C'). If not provided, returns all mark prices") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.mark({ - ...(params.symbol && { symbol: params.symbol }) - }); - - const data = await response.data(); - - let result = `✅ Options Mark Prices\n\n`; - - if (Array.isArray(data)) { - result += `Total contracts: ${data.length}\n\n`; - data.slice(0, 20).forEach((item: any) => { - result += `**${item.symbol}**\n`; - result += ` Mark Price: ${item.markPrice}\n`; - result += ` Bid IV: ${item.bidIV} | Ask IV: ${item.askIV}\n`; - result += ` Mark IV: ${item.markIV}\n`; - result += ` Delta: ${item.delta} | Theta: ${item.theta}\n`; - result += ` Gamma: ${item.gamma} | Vega: ${item.vega}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more contracts`; - } - } else if (data) { - result += `**${data.symbol}**\n`; - result += `Mark Price: ${data.markPrice}\n`; - result += `Bid IV: ${data.bidIV} | Ask IV: ${data.askIV}\n`; - result += `Mark IV: ${data.markIV}\n`; - result += `Delta: ${data.delta} | Theta: ${data.theta}\n`; - result += `Gamma: ${data.gamma} | Vega: ${data.vega}\n`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options mark prices: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Option symbol (e.g., 'BTC-240126-40000-C'). If not provided, returns all mark prices", + ), + }, + }, + async (params) => { + try { + const data = await optionsClient.mark({ + ...(params.symbol && { symbol: params.symbol }), + }); + + let result = `✅ Options Mark Prices\n\n`; + + if (Array.isArray(data)) { + result += `Total contracts: ${data.length}\n\n`; + data.slice(0, 20).forEach((item: any) => { + result += `**${item.symbol}**\n`; + result += ` Mark Price: ${item.markPrice}\n`; + result += ` Bid IV: ${item.bidIV} | Ask IV: ${item.askIV}\n`; + result += ` Mark IV: ${item.markIV}\n`; + result += ` Delta: ${item.delta} | Theta: ${item.theta}\n`; + result += ` Gamma: ${item.gamma} | Vega: ${item.vega}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more contracts`; + } + } else if (data) { + result += `**${data.symbol}**\n`; + result += `Mark Price: ${data.markPrice}\n`; + result += `Bid IV: ${data.bidIV} | Ask IV: ${data.askIV}\n`; + result += `Mark IV: ${data.markIV}\n`; + result += `Delta: ${data.delta} | Theta: ${data.theta}\n`; + result += `Gamma: ${data.gamma} | Vega: ${data.vega}\n`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options mark prices: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/ping.ts b/src/modules/options/market-api/ping.ts index dcf972df..dcd5152b 100644 --- a/src/modules/options/market-api/ping.ts +++ b/src/modules/options/market-api/ping.ts @@ -5,35 +5,39 @@ * @license Apache-2.0 */ // src/modules/options/market-api/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../../config/binanceClient.js"; export function registerOptionsMarketPing(server: McpServer) { - server.tool( - "BinanceOptionsPing", - "Test connectivity to the Options API. Returns empty object if successful.", - {}, - async () => { - try { - const response = await optionsClient.restAPI.ping(); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options API connectivity test successful!\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Options API connectivity test failed: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsPing", + { description: "Test connectivity to the Options API. Returns empty object if successful." }, + async () => { + try { + const data = await optionsClient.ping(); + + return { + content: [ + { + type: "text", + text: `✅ Options API connectivity test successful!\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Options API connectivity test failed: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/ticker.ts b/src/modules/options/market-api/ticker.ts index 46c2ff40..00c05546 100644 --- a/src/modules/options/market-api/ticker.ts +++ b/src/modules/options/market-api/ticker.ts @@ -5,67 +5,80 @@ * @license Apache-2.0 */ // src/modules/options/market-api/ticker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketTicker(server: McpServer) { - server.tool( - "BinanceOptionsTicker", + server.registerTool( + "BinanceOptionsTicker", + { + description: "Get 24hr ticker price change statistics for options contracts. Returns price change, volume, and other trading stats.", - { - symbol: z.string().optional() - .describe("Option symbol (e.g., 'BTC-240126-40000-C'). If not provided, returns all tickers") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.ticker({ - ...(params.symbol && { symbol: params.symbol }) - }); - - const data = await response.data(); - - let result = `✅ Options 24hr Ticker Statistics\n\n`; - - const formatTicker = (ticker: any) => { - let str = `**${ticker.symbol}**\n`; - str += ` Price Change: ${ticker.priceChange} (${ticker.priceChangePercent}%)\n`; - str += ` Last Price: ${ticker.lastPrice}\n`; - str += ` High: ${ticker.high} | Low: ${ticker.low}\n`; - str += ` Volume: ${ticker.volume}\n`; - str += ` Quote Volume: ${ticker.quoteVolume}\n`; - str += ` Open Interest: ${ticker.openInterest}\n`; - return str; - }; - - if (Array.isArray(data)) { - result += `Total contracts: ${data.length}\n\n`; - data.slice(0, 15).forEach((ticker: any) => { - result += formatTicker(ticker) + '\n'; - }); - if (data.length > 15) { - result += `... and ${data.length - 15} more contracts`; - } - } else if (data) { - result += formatTicker(data); - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options ticker: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Option symbol (e.g., 'BTC-240126-40000-C'). If not provided, returns all tickers", + ), + }, + }, + async (params) => { + try { + const data = await optionsClient.ticker({ + ...(params.symbol && { symbol: params.symbol }), + }); + + let result = `✅ Options 24hr Ticker Statistics\n\n`; + + const formatTicker = (ticker: any) => { + let str = `**${ticker.symbol}**\n`; + str += ` Price Change: ${ticker.priceChange} (${ticker.priceChangePercent}%)\n`; + str += ` Last Price: ${ticker.lastPrice}\n`; + str += ` High: ${ticker.high} | Low: ${ticker.low}\n`; + str += ` Volume: ${ticker.volume}\n`; + str += ` Quote Volume: ${ticker.quoteVolume}\n`; + str += ` Open Interest: ${ticker.openInterest}\n`; + + return str; + }; + + if (Array.isArray(data)) { + result += `Total contracts: ${data.length}\n\n`; + data.slice(0, 15).forEach((ticker: any) => { + result += formatTicker(ticker) + "\n"; + }); + if (data.length > 15) { + result += `... and ${data.length - 15} more contracts`; + } + } else if (data) { + result += formatTicker(data); } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options ticker: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/time.ts b/src/modules/options/market-api/time.ts index 1b049745..b0dfaef6 100644 --- a/src/modules/options/market-api/time.ts +++ b/src/modules/options/market-api/time.ts @@ -5,37 +5,41 @@ * @license Apache-2.0 */ // src/modules/options/market-api/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../../config/binanceClient.js"; export function registerOptionsMarketTime(server: McpServer) { - server.tool( - "BinanceOptionsTime", - "Get the current server time from the Options API.", - {}, - async () => { - try { - const response = await optionsClient.restAPI.time(); - const data = await response.data(); - - const serverTime = new Date(data.serverTime).toISOString(); - - return { - content: [{ - type: "text", - text: `✅ Options Server Time\n\nTimestamp: ${data.serverTime}\nUTC: ${serverTime}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options server time: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsTime", + { description: "Get the current server time from the Options API." }, + async () => { + try { + const data = await optionsClient.time(); + + const serverTime = new Date(data.serverTime).toISOString(); + + return { + content: [ + { + type: "text", + text: `✅ Options Server Time\n\nTimestamp: ${data.serverTime}\nUTC: ${serverTime}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options server time: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/market-api/trades.ts b/src/modules/options/market-api/trades.ts index 66c4b463..5a0fd84b 100644 --- a/src/modules/options/market-api/trades.ts +++ b/src/modules/options/market-api/trades.ts @@ -5,59 +5,72 @@ * @license Apache-2.0 */ // src/modules/options/market-api/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsMarketTrades(server: McpServer) { - server.tool( - "BinanceOptionsTrades", + server.registerTool( + "BinanceOptionsTrades", + { + description: "Get recent trades for an options contract. Shows the most recent executed trades.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - limit: z.number().int().min(1).max(500).optional() - .describe("Number of trades to return (default 100, max 500)") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.trades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - let result = `✅ Recent Trades - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades returned: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - const time = new Date(trade.time).toISOString(); - result += `${index + 1}. Price: ${trade.price} | Qty: ${trade.qty} | Time: ${time}\n`; - }); - if (data.length > 20) { - result += `\n... and ${data.length - 20} more trades`; - } - } else { - result += `No recent trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Options trades: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + limit: z + .number() + .int() + .min(1) + .max(500) + .optional() + .describe("Number of trades to return (default 100, max 500)"), + }, + }, + async (params) => { + try { + const data = await optionsClient.trades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + + let result = `✅ Recent Trades - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades returned: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + const time = new Date(trade.time).toISOString(); + result += `${index + 1}. Price: ${trade.price} | Qty: ${trade.qty} | Time: ${time}\n`; + }); + if (data.length > 20) { + result += `\n... and ${data.length - 20} more trades`; + } + } else { + result += `No recent trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Options trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/batchOrders.ts b/src/modules/options/trade-api/batchOrders.ts index ddc2f619..d03bd70a 100644 --- a/src/modules/options/trade-api/batchOrders.ts +++ b/src/modules/options/trade-api/batchOrders.ts @@ -5,70 +5,84 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsBatchOrders(server: McpServer) { - server.tool( - "BinanceOptionsBatchOrders", + server.registerTool( + "BinanceOptionsBatchOrders", + { + description: "Place multiple options orders in a single request. Maximum 5 orders per request. ⚠️ HIGH RISK: Options can expire worthless.", - { - orders: z.array(z.object({ - symbol: z.string().describe("Option symbol"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT"]).describe("Order type"), - quantity: z.string().describe("Number of contracts"), - price: z.string().describe("Limit price"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional(), - reduceOnly: z.boolean().optional(), - postOnly: z.boolean().optional(), - newClientOrderId: z.string().optional() - })).min(1).max(5).describe("Array of orders (max 5)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.batchOrders({ - orders: JSON.stringify(params.orders), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Batch Options Orders Placed\n\n`; - - if (Array.isArray(data)) { - data.forEach((order: any, index: number) => { - if (order.orderId) { - result += `Order ${index + 1}: ✅ Success\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Symbol: ${order.symbol}\n`; - result += ` Side: ${order.side} | Qty: ${order.quantity}\n`; - result += ` Price: ${order.price} | Status: ${order.status}\n\n`; - } else { - result += `Order ${index + 1}: ❌ Failed\n`; - result += ` Error: ${order.msg || 'Unknown error'}\n\n`; - } - }); - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place batch options orders: ${errorMessage}` - }], - isError: true - }; + inputSchema: { + orders: z + .array( + z.object({ + symbol: z.string().describe("Option symbol"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z.enum(["LIMIT"]).describe("Order type"), + quantity: z.string().describe("Number of contracts"), + price: z.string().describe("Limit price"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional(), + reduceOnly: z.boolean().optional(), + postOnly: z.boolean().optional(), + newClientOrderId: z.string().optional(), + }), + ) + .min(1) + .max(5) + .describe("Array of orders (max 5)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.batchOrders({ + orders: JSON.stringify(params.orders), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Batch Options Orders Placed\n\n`; + + if (Array.isArray(data)) { + data.forEach((order: any, index: number) => { + if (order.orderId) { + result += `Order ${index + 1}: ✅ Success\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Symbol: ${order.symbol}\n`; + result += ` Side: ${order.side} | Qty: ${order.quantity}\n`; + result += ` Price: ${order.price} | Status: ${order.status}\n\n`; + } else { + result += `Order ${index + 1}: ❌ Failed\n`; + result += ` Error: ${order.msg || "Unknown error"}\n\n`; } + }); } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place batch options orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/cancelAllOrders.ts b/src/modules/options/trade-api/cancelAllOrders.ts index c7ed6906..9e9c1afc 100644 --- a/src/modules/options/trade-api/cancelAllOrders.ts +++ b/src/modules/options/trade-api/cancelAllOrders.ts @@ -5,43 +5,51 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsCancelAllOrders(server: McpServer) { - server.tool( - "BinanceOptionsCancelAllOrders", + server.registerTool( + "BinanceOptionsCancelAllOrders", + { + description: "Cancel all open options orders for a specific symbol. ⚠️ This will cancel ALL open orders for the symbol.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.cancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All open orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel all options orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.cancelAllOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `✅ All open orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel all options orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/cancelBatchOrders.ts b/src/modules/options/trade-api/cancelBatchOrders.ts index 52163a99..51efc84e 100644 --- a/src/modules/options/trade-api/cancelBatchOrders.ts +++ b/src/modules/options/trade-api/cancelBatchOrders.ts @@ -5,73 +5,89 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceOptionsCancelBatchOrders", + server.registerTool( + "BinanceOptionsCancelBatchOrders", + { + description: "Cancel multiple options orders in a single request. Maximum 5 orders per request.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - orderIds: z.array(z.number().int()).optional().describe("Array of order IDs to cancel (max 5)"), - clientOrderIds: z.array(z.string()).optional().describe("Array of client order IDs to cancel (max 5)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderIds && !params.clientOrderIds) { - return { - content: [{ - type: "text", - text: `❌ Either orderIds or clientOrderIds must be provided` - }], - isError: true - }; - } - - const response = await optionsClient.restAPI.cancelBatchOrders({ - symbol: params.symbol, - ...(params.orderIds && { orderIds: JSON.stringify(params.orderIds) }), - ...(params.clientOrderIds && { clientOrderIds: JSON.stringify(params.clientOrderIds) }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Batch Options Orders Cancelled\n\n`; - - if (Array.isArray(data)) { - data.forEach((order: any, index: number) => { - if (order.orderId && !order.code) { - result += `Order ${index + 1}: ✅ Cancelled\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Symbol: ${order.symbol}\n`; - result += ` Status: ${order.status}\n\n`; - } else { - result += `Order ${index + 1}: ❌ Failed\n`; - result += ` Error: ${order.msg || 'Unknown error'}\n\n`; - } - }); - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel batch options orders: ${errorMessage}` - }], - isError: true - }; + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + orderIds: z + .array(z.number().int()) + .optional() + .describe("Array of order IDs to cancel (max 5)"), + clientOrderIds: z + .array(z.string()) + .optional() + .describe("Array of client order IDs to cancel (max 5)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderIds && !params.clientOrderIds) { + return { + content: [ + { + type: "text", + text: `❌ Either orderIds or clientOrderIds must be provided`, + }, + ], + isError: true, + }; + } + + const data = await optionsClient.cancelBatchOrders({ + symbol: params.symbol, + ...(params.orderIds && { orderIds: JSON.stringify(params.orderIds) }), + ...(params.clientOrderIds && { clientOrderIds: JSON.stringify(params.clientOrderIds) }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Batch Options Orders Cancelled\n\n`; + + if (Array.isArray(data)) { + data.forEach((order: any, index: number) => { + if (order.orderId && !order.code) { + result += `Order ${index + 1}: ✅ Cancelled\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Symbol: ${order.symbol}\n`; + result += ` Status: ${order.status}\n\n`; + } else { + result += `Order ${index + 1}: ❌ Failed\n`; + result += ` Error: ${order.msg || "Unknown error"}\n\n`; } + }); } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel batch options orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/cancelBySymbol.ts b/src/modules/options/trade-api/cancelBySymbol.ts index 5083904e..9741c740 100644 --- a/src/modules/options/trade-api/cancelBySymbol.ts +++ b/src/modules/options/trade-api/cancelBySymbol.ts @@ -5,43 +5,51 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/cancelBySymbol.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsCancelBySymbol(server: McpServer) { - server.tool( - "BinanceOptionsCancelByUnderlying", + server.registerTool( + "BinanceOptionsCancelByUnderlying", + { + description: "Cancel all open options orders for all contracts of an underlying asset (e.g., all BTC options). ⚠️ This will cancel ALL open orders for the underlying.", - { - underlying: z.string().describe("Underlying asset (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.cancelAllOpenOrdersByUnderlying({ - underlying: params.underlying, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All open orders cancelled for underlying ${params.underlying}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel orders by underlying: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + underlying: z.string().describe("Underlying asset (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.cancelAllOpenOrdersByUnderlying({ + underlying: params.underlying, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `✅ All open orders cancelled for underlying ${params.underlying}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel orders by underlying: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/cancelOrder.ts b/src/modules/options/trade-api/cancelOrder.ts index 1f4dded0..c154759c 100644 --- a/src/modules/options/trade-api/cancelOrder.ts +++ b/src/modules/options/trade-api/cancelOrder.ts @@ -5,57 +5,66 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsCancelOrder(server: McpServer) { - server.tool( - "BinanceOptionsCancelOrder", - "Cancel an active options order by order ID or client order ID.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - clientOrderId: z.string().optional().describe("Client order ID to cancel"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.clientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or clientOrderId must be provided` - }], - isError: true - }; - } - - const response = await optionsClient.restAPI.cancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options order cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nQuantity: ${data.quantity}\nPrice: ${data.price}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel options order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsCancelOrder", + { + description: "Cancel an active options order by order ID or client order ID.", + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + clientOrderId: z.string().optional().describe("Client order ID to cancel"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.clientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or clientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const data = await optionsClient.cancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `✅ Options order cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nQuantity: ${data.quantity}\nPrice: ${data.price}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel options order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/getHistoryOrders.ts b/src/modules/options/trade-api/getHistoryOrders.ts index 21385e69..ae057d20 100644 --- a/src/modules/options/trade-api/getHistoryOrders.ts +++ b/src/modules/options/trade-api/getHistoryOrders.ts @@ -5,71 +5,84 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/getHistoryOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetHistoryOrders(server: McpServer) { - server.tool( - "BinanceOptionsGetHistoryOrders", - "Get historical options orders. Returns filled, cancelled, and expired orders.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of orders to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.historyOrders({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Order History - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total orders: ${data.length}\n\n`; - data.slice(0, 20).forEach((order: any, index: number) => { - result += `**${index + 1}. Order ID: ${order.orderId}**\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.quantity}\n`; - result += ` Executed Qty: ${order.executedQty}\n`; - result += ` Avg Price: ${order.avgPrice}\n`; - result += ` Status: ${order.status}\n`; - result += ` Time: ${new Date(order.createTime).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more orders`; - } - } else { - result += `No historical orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options order history: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsGetHistoryOrders", + { + description: "Get historical options orders. Returns filled, cancelled, and expired orders.", + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of orders to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.historyOrders({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Order History - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total orders: ${data.length}\n\n`; + data.slice(0, 20).forEach((order: any, index: number) => { + result += `**${index + 1}. Order ID: ${order.orderId}**\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.quantity}\n`; + result += ` Executed Qty: ${order.executedQty}\n`; + result += ` Avg Price: ${order.avgPrice}\n`; + result += ` Status: ${order.status}\n`; + result += ` Time: ${new Date(order.createTime).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more orders`; + } + } else { + result += `No historical orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options order history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/getOpenOrders.ts b/src/modules/options/trade-api/getOpenOrders.ts index 4a65645f..3ace9da4 100644 --- a/src/modules/options/trade-api/getOpenOrders.ts +++ b/src/modules/options/trade-api/getOpenOrders.ts @@ -5,62 +5,72 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetOpenOrders(server: McpServer) { - server.tool( - "BinanceOptionsGetOpenOrders", - "Get all open options orders. Can filter by symbol or underlying asset.", - { - symbol: z.string().optional().describe("Option symbol to filter by"), - underlying: z.string().optional().describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.openOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.underlying && { underlying: params.underlying }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Open Options Orders\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total open orders: ${data.length}\n\n`; - data.forEach((order: any, index: number) => { - result += `**${index + 1}. ${order.symbol}**\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.quantity}\n`; - result += ` Executed Qty: ${order.executedQty}\n`; - result += ` Status: ${order.status}\n`; - result += ` Time: ${new Date(order.createTime).toISOString()}\n\n`; - }); - } else { - result += `No open orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get open options orders: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinanceOptionsGetOpenOrders", + { + description: "Get all open options orders. Can filter by symbol or underlying asset.", + inputSchema: { + symbol: z.string().optional().describe("Option symbol to filter by"), + underlying: z + .string() + .optional() + .describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.openOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.underlying && { underlying: params.underlying }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Open Options Orders\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total open orders: ${data.length}\n\n`; + data.forEach((order: any, index: number) => { + result += `**${index + 1}. ${order.symbol}**\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.quantity}\n`; + result += ` Executed Qty: ${order.executedQty}\n`; + result += ` Status: ${order.status}\n`; + result += ` Time: ${new Date(order.createTime).toISOString()}\n\n`; + }); + } else { + result += `No open orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get open options orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/getUserTrades.ts b/src/modules/options/trade-api/getUserTrades.ts index 68fb598b..dea4518c 100644 --- a/src/modules/options/trade-api/getUserTrades.ts +++ b/src/modules/options/trade-api/getUserTrades.ts @@ -5,74 +5,91 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/getUserTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsGetUserTrades(server: McpServer) { - server.tool( - "BinanceOptionsGetUserTrades", + server.registerTool( + "BinanceOptionsGetUserTrades", + { + description: "Get user's options trade history. Returns executed trades with prices and quantities.", - { - symbol: z.string().optional().describe("Option symbol to filter by"), - underlying: z.string().optional().describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), - fromId: z.number().int().optional().describe("Trade ID to fetch from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of trades to return (default 100, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.userTrades({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.underlying && { underlying: params.underlying }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Options Trade History\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - result += `**${index + 1}. ${trade.symbol}**\n`; - result += ` Trade ID: ${trade.id}\n`; - result += ` Order ID: ${trade.orderId}\n`; - result += ` Side: ${trade.side}\n`; - result += ` Price: ${trade.price} | Qty: ${trade.quantity}\n`; - result += ` Fee: ${trade.fee} ${trade.feeAsset}\n`; - result += ` Realized PnL: ${trade.realizedProfit}\n`; - result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more trades`; - } - } else { - result += `No trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get options trades: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().optional().describe("Option symbol to filter by"), + underlying: z + .string() + .optional() + .describe("Underlying asset to filter by (e.g., 'BTCUSDT')"), + fromId: z.number().int().optional().describe("Trade ID to fetch from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of trades to return (default 100, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.userTrades({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.underlying && { underlying: params.underlying }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + let result = `✅ Options Trade History\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + result += `**${index + 1}. ${trade.symbol}**\n`; + result += ` Trade ID: ${trade.id}\n`; + result += ` Order ID: ${trade.orderId}\n`; + result += ` Side: ${trade.side}\n`; + result += ` Price: ${trade.price} | Qty: ${trade.quantity}\n`; + result += ` Fee: ${trade.fee} ${trade.feeAsset}\n`; + result += ` Realized PnL: ${trade.realizedProfit}\n`; + result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more trades`; + } + } else { + result += `No trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get options trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/trade-api/index.ts b/src/modules/options/trade-api/index.ts index d25e76e7..aa3200a0 100644 --- a/src/modules/options/trade-api/index.ts +++ b/src/modules/options/trade-api/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerOptionsNewOrder } from "./newOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerOptionsBatchOrders } from "./batchOrders.js"; -import { registerOptionsCancelOrder } from "./cancelOrder.js"; -import { registerOptionsCancelBatchOrders } from "./cancelBatchOrders.js"; import { registerOptionsCancelAllOrders } from "./cancelAllOrders.js"; +import { registerOptionsCancelBatchOrders } from "./cancelBatchOrders.js"; import { registerOptionsCancelBySymbol } from "./cancelBySymbol.js"; -import { registerOptionsGetOpenOrders } from "./getOpenOrders.js"; +import { registerOptionsCancelOrder } from "./cancelOrder.js"; import { registerOptionsGetHistoryOrders } from "./getHistoryOrders.js"; +import { registerOptionsGetOpenOrders } from "./getOpenOrders.js"; import { registerOptionsGetUserTrades } from "./getUserTrades.js"; +import { registerOptionsNewOrder } from "./newOrder.js"; export function registerOptionsTradeApi(server: McpServer) { - registerOptionsNewOrder(server); - registerOptionsBatchOrders(server); - registerOptionsCancelOrder(server); - registerOptionsCancelBatchOrders(server); - registerOptionsCancelAllOrders(server); - registerOptionsCancelBySymbol(server); - registerOptionsGetOpenOrders(server); - registerOptionsGetHistoryOrders(server); - registerOptionsGetUserTrades(server); + registerOptionsNewOrder(server); + registerOptionsBatchOrders(server); + registerOptionsCancelOrder(server); + registerOptionsCancelBatchOrders(server); + registerOptionsCancelAllOrders(server); + registerOptionsCancelBySymbol(server); + registerOptionsGetOpenOrders(server); + registerOptionsGetHistoryOrders(server); + registerOptionsGetUserTrades(server); } diff --git a/src/modules/options/trade-api/newOrder.ts b/src/modules/options/trade-api/newOrder.ts index e18e6178..bbcf8797 100644 --- a/src/modules/options/trade-api/newOrder.ts +++ b/src/modules/options/trade-api/newOrder.ts @@ -5,62 +5,72 @@ * @license Apache-2.0 */ // src/modules/options/trade-api/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsNewOrder(server: McpServer) { - server.tool( - "BinanceOptionsNewOrder", + server.registerTool( + "BinanceOptionsNewOrder", + { + description: "Place a new options order. Options trading allows you to buy/sell call and put contracts. ⚠️ HIGH RISK: Options can expire worthless.", - { - symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT"]).describe("Order type (only LIMIT supported)"), - quantity: z.string().describe("Number of contracts"), - price: z.string().describe("Limit price per contract"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional() - .describe("Time in force (default: GTC)"), - reduceOnly: z.boolean().optional().describe("Reduce position only (default: false)"), - postOnly: z.boolean().optional().describe("Post only order (default: false)"), - newClientOrderId: z.string().optional().describe("Custom client order ID"), - isMmp: z.boolean().optional().describe("Is market maker protection order"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.newOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - quantity: params.quantity, - price: params.price, - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.postOnly !== undefined && { postOnly: params.postOnly }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.isMmp !== undefined && { isMmp: params.isMmp }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options order placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.quantity}\nPrice: ${data.price}\nStatus: ${data.status}\nClient Order ID: ${data.clientOrderId || 'N/A'}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place options order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Option symbol (e.g., 'BTC-240126-40000-C')"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z.enum(["LIMIT"]).describe("Order type (only LIMIT supported)"), + quantity: z.string().describe("Number of contracts"), + price: z.string().describe("Limit price per contract"), + timeInForce: z + .enum(["GTC", "IOC", "FOK"]) + .optional() + .describe("Time in force (default: GTC)"), + reduceOnly: z.boolean().optional().describe("Reduce position only (default: false)"), + postOnly: z.boolean().optional().describe("Post only order (default: false)"), + newClientOrderId: z.string().optional().describe("Custom client order ID"), + isMmp: z.boolean().optional().describe("Is market maker protection order"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const data = await optionsClient.newOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + quantity: params.quantity, + price: params.price, + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.postOnly !== undefined && { postOnly: params.postOnly }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.isMmp !== undefined && { isMmp: params.isMmp }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `✅ Options order placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.quantity}\nPrice: ${data.price}\nStatus: ${data.status}\nClient Order ID: ${data.clientOrderId || "N/A"}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place options order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/userdata-api/createListenKey.ts b/src/modules/options/userdata-api/createListenKey.ts index 8fab31ae..e9c9ad71 100644 --- a/src/modules/options/userdata-api/createListenKey.ts +++ b/src/modules/options/userdata-api/createListenKey.ts @@ -5,35 +5,42 @@ * @license Apache-2.0 */ // src/modules/options/userdata-api/createListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../../config/binanceClient.js"; export function registerOptionsCreateListenKey(server: McpServer) { - server.tool( - "BinanceOptionsCreateListenKey", + server.registerTool( + "BinanceOptionsCreateListenKey", + { + description: "Create a listen key for options user data stream. The listen key is used to subscribe to account updates via WebSocket.", - {}, - async () => { - try { - const response = await optionsClient.restAPI.createListenKey(); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options Listen Key Created\n\nListen Key: ${data.listenKey}\n\n**Note**: This listen key is valid for 60 minutes. Use BinanceOptionsRenewListenKey to extend validity. Use this key to connect to the WebSocket user data stream.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to create options listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + }, + async () => { + try { + const data = await optionsClient.createListenKey(); + + return { + content: [ + { + type: "text", + text: `✅ Options Listen Key Created\n\nListen Key: ${data.listenKey}\n\n**Note**: This listen key is valid for 60 minutes. Use BinanceOptionsRenewListenKey to extend validity. Use this key to connect to the WebSocket user data stream.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to create options listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/userdata-api/deleteListenKey.ts b/src/modules/options/userdata-api/deleteListenKey.ts index 310b13a3..1abc8027 100644 --- a/src/modules/options/userdata-api/deleteListenKey.ts +++ b/src/modules/options/userdata-api/deleteListenKey.ts @@ -5,40 +5,52 @@ * @license Apache-2.0 */ // src/modules/options/userdata-api/deleteListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsDeleteListenKey(server: McpServer) { - server.tool( - "BinanceOptionsDeleteListenKey", + server.registerTool( + "BinanceOptionsDeleteListenKey", + { + description: "Close/delete an options listen key. This will terminate the user data stream connection.", - { - listenKey: z.string().optional().describe("Listen key to delete. If not provided, deletes the current active key") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.deleteListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }) - }); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options Listen Key Deleted\n\nThe listen key has been invalidated and the user data stream will be closed.\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to delete options listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z + .string() + .optional() + .describe("Listen key to delete. If not provided, deletes the current active key"), + }, + }, + async (params) => { + try { + const data = await optionsClient.closeListenKey( + params.listenKey ? { listenKey: params.listenKey } : {}, + ); + + return { + content: [ + { + type: "text", + text: `✅ Options Listen Key Deleted\n\nThe listen key has been invalidated and the user data stream will be closed.\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to delete options listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/options/userdata-api/index.ts b/src/modules/options/userdata-api/index.ts index 334a3494..baa10558 100644 --- a/src/modules/options/userdata-api/index.ts +++ b/src/modules/options/userdata-api/index.ts @@ -5,13 +5,14 @@ * @license Apache-2.0 */ // src/modules/options/userdata-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerOptionsCreateListenKey } from "./createListenKey.js"; -import { registerOptionsRenewListenKey } from "./renewListenKey.js"; import { registerOptionsDeleteListenKey } from "./deleteListenKey.js"; +import { registerOptionsRenewListenKey } from "./renewListenKey.js"; export function registerOptionsUserdataApi(server: McpServer) { - registerOptionsCreateListenKey(server); - registerOptionsRenewListenKey(server); - registerOptionsDeleteListenKey(server); + registerOptionsCreateListenKey(server); + registerOptionsRenewListenKey(server); + registerOptionsDeleteListenKey(server); } diff --git a/src/modules/options/userdata-api/renewListenKey.ts b/src/modules/options/userdata-api/renewListenKey.ts index 350e81e0..da797bdb 100644 --- a/src/modules/options/userdata-api/renewListenKey.ts +++ b/src/modules/options/userdata-api/renewListenKey.ts @@ -5,40 +5,52 @@ * @license Apache-2.0 */ // src/modules/options/userdata-api/renewListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { optionsClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { optionsClient } from "../../../config/binanceClient.js"; + export function registerOptionsRenewListenKey(server: McpServer) { - server.tool( - "BinanceOptionsRenewListenKey", + server.registerTool( + "BinanceOptionsRenewListenKey", + { + description: "Extend the validity of an options listen key by 60 minutes. Should be called periodically to keep the user data stream active.", - { - listenKey: z.string().optional().describe("Listen key to renew. If not provided, renews the current active key") - }, - async (params) => { - try { - const response = await optionsClient.restAPI.renewListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }) - }); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Options Listen Key Renewed\n\nThe listen key validity has been extended by 60 minutes.\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to renew options listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z + .string() + .optional() + .describe("Listen key to renew. If not provided, renews the current active key"), + }, + }, + async (params) => { + try { + const data = await optionsClient.keepAliveListenKey( + params.listenKey ? { listenKey: params.listenKey } : {}, + ); + + return { + content: [ + { + type: "text", + text: `✅ Options Listen Key Renewed\n\nThe listen key validity has been extended by 60 minutes.\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to renew options listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/pay/index.ts b/src/modules/pay/index.ts index e5640021..9a791d5a 100644 --- a/src/modules/pay/index.ts +++ b/src/modules/pay/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-pay/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetPayTradeHistory } from "./pay-api/getPayTradeHistory.js"; export function registerBinancePayTools(server: McpServer) { - registerBinanceGetPayTradeHistory(server); + registerBinanceGetPayTradeHistory(server); } // Alias for binance.ts compatibility diff --git a/src/modules/pay/pay-api/createOrder.ts b/src/modules/pay/pay-api/createOrder.ts index bb120a39..8ce884ac 100644 --- a/src/modules/pay/pay-api/createOrder.ts +++ b/src/modules/pay/pay-api/createOrder.ts @@ -5,55 +5,65 @@ * @license Apache-2.0 */ // src/modules/pay/pay-api/createOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { payClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { payClient } from "../../../config/binanceClient.js"; + export function registerBinancePayCreateOrder(server: McpServer) { - server.tool( - "BinancePayCreateOrder", + server.registerTool( + "BinancePayCreateOrder", + { + description: "Create a Binance Pay order for receiving crypto payments. Generate payment links for e-commerce or P2P transactions. 💳", - { - merchantId: z.string().optional().describe("Merchant ID (for business accounts)"), - orderId: z.string().describe("Unique order ID for your reference"), - currency: z.string().describe("Payment currency (e.g., 'USDT', 'BTC')"), - totalAmount: z.string().describe("Total payment amount"), - description: z.string().optional().describe("Order description"), - goodsName: z.string().optional().describe("Name of goods/service"), - goodsDetail: z.string().optional().describe("Details of goods/service"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await payClient.restAPI.createOrder({ - orderId: params.orderId, - currency: params.currency, - totalAmount: params.totalAmount, - ...(params.merchantId && { merchantId: params.merchantId }), - ...(params.description && { description: params.description }), - ...(params.goodsName && { goodsName: params.goodsName }), - ...(params.goodsDetail && { goodsDetail: params.goodsDetail }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + merchantId: z.string().optional().describe("Merchant ID (for business accounts)"), + orderId: z.string().describe("Unique order ID for your reference"), + currency: z.string().describe("Payment currency (e.g., 'USDT', 'BTC')"), + totalAmount: z.string().describe("Total payment amount"), + description: z.string().optional().describe("Order description"), + goodsName: z.string().optional().describe("Name of goods/service"), + goodsDetail: z.string().optional().describe("Details of goods/service"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (payClient as any).restAPI.createOrder({ + orderId: params.orderId, + currency: params.currency, + totalAmount: params.totalAmount, + ...(params.merchantId && { merchantId: params.merchantId }), + ...(params.description && { description: params.description }), + ...(params.goodsName && { goodsName: params.goodsName }), + ...(params.goodsDetail && { goodsDetail: params.goodsDetail }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Binance Pay Order Created!\n\nOrder ID: ${params.orderId}\nCurrency: ${params.currency}\nAmount: ${params.totalAmount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Binance Pay Order Created!\n\nOrder ID: ${params.orderId}\nCurrency: ${params.currency}\nAmount: ${params.totalAmount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to create pay order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to create pay order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/pay/pay-api/getHistory.ts b/src/modules/pay/pay-api/getHistory.ts index 80435eb6..90aef64e 100644 --- a/src/modules/pay/pay-api/getHistory.ts +++ b/src/modules/pay/pay-api/getHistory.ts @@ -5,47 +5,63 @@ * @license Apache-2.0 */ // src/modules/pay/pay-api/getHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { payClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { payClient } from "../../../config/binanceClient.js"; + export function registerBinancePayGetHistory(server: McpServer) { - server.tool( - "BinancePayGetHistory", + server.registerTool( + "BinancePayGetHistory", + { + description: "Get your Binance Pay transaction history. Shows all Pay transactions including C2C transfers, merchant payments, and refunds.", - { - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - limit: z.number().int().max(100).default(100).optional().describe("Number of records (max 100)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await payClient.restAPI.getPayTradeHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + limit: z + .number() + .int() + .max(100) + .default(100) + .optional() + .describe("Number of records (max 100)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (payClient as any).restAPI.getPayTradeHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Binance Pay Transaction History\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Binance Pay Transaction History\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get pay history: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get pay history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/pay/pay-api/getPayTradeHistory.ts b/src/modules/pay/pay-api/getPayTradeHistory.ts index d37b514c..4c059bf1 100644 --- a/src/modules/pay/pay-api/getPayTradeHistory.ts +++ b/src/modules/pay/pay-api/getPayTradeHistory.ts @@ -1,54 +1,64 @@ // src/tools/binance-pay/pay-api/getPayTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { payClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { payClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetPayTradeHistory(server: McpServer) { - server.tool( - "BinanceGetPayTradeHistory", + server.registerTool( + "BinanceGetPayTradeHistory", + { + description: "Retrieve Binance Pay trade history using GET to fetch transaction records such as C2C transfers, merchant payments, crypto box activity, refunds, payouts, and remittance details.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(100, "Limit cannot be greater than 100") - .default(100) - .describe("Number of records to return, default 100, max 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await payClient.restAPI.getPayTradeHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(100, "Limit cannot be greater than 100") + .default(100) + .describe("Number of records to return, default 100, max 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (payClient as any).restAPI.getPayTradeHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved Binance Pay trade history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved Binance Pay trade history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve Binance Pay trade history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve Binance Pay trade history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/pay/pay-api/queryOrder.ts b/src/modules/pay/pay-api/queryOrder.ts index 22a7b508..1df479b4 100644 --- a/src/modules/pay/pay-api/queryOrder.ts +++ b/src/modules/pay/pay-api/queryOrder.ts @@ -5,47 +5,56 @@ * @license Apache-2.0 */ // src/modules/pay/pay-api/queryOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { payClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { payClient } from "../../../config/binanceClient.js"; + export function registerBinancePayQueryOrder(server: McpServer) { - server.tool( - "BinancePayQueryOrder", - "Query the status of a Binance Pay order. Check if payment has been received.", - { - merchantId: z.string().optional().describe("Merchant ID"), - prepayId: z.string().optional().describe("Prepay ID from order creation"), - merchantTradeNo: z.string().optional().describe("Your merchant trade number"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await payClient.restAPI.queryOrder({ - ...(params.merchantId && { merchantId: params.merchantId }), - ...(params.prepayId && { prepayId: params.prepayId }), - ...(params.merchantTradeNo && { merchantTradeNo: params.merchantTradeNo }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinancePayQueryOrder", + { + description: "Query the status of a Binance Pay order. Check if payment has been received.", + inputSchema: { + merchantId: z.string().optional().describe("Merchant ID"), + prepayId: z.string().optional().describe("Prepay ID from order creation"), + merchantTradeNo: z.string().optional().describe("Your merchant trade number"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (payClient as any).restAPI.queryOrder({ + ...(params.merchantId && { merchantId: params.merchantId }), + ...(params.prepayId && { prepayId: params.prepayId }), + ...(params.merchantTradeNo && { merchantTradeNo: params.merchantTradeNo }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📋 Binance Pay Order Status\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 Binance Pay Order Status\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to query pay order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to query pay order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getAccountInfo.ts b/src/modules/portfolio-margin/account/getAccountInfo.ts index 9a0f8f5b..2db214db 100644 --- a/src/modules/portfolio-margin/account/getAccountInfo.ts +++ b/src/modules/portfolio-margin/account/getAccountInfo.ts @@ -5,56 +5,66 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getAccountInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetAccountInfo(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAccount", + server.registerTool( + "BinancePortfolioMarginGetAccount", + { + description: "Get Portfolio Margin account information including unified account equity, margin status, and risk levels.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.account({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Account Information\n\n`; - - if (data) { - result += `**Account Status**\n`; - result += `UniMMR: ${data.uniMMR}\n`; - result += `Account Equity: ${data.accountEquity}\n`; - result += `Actual Equity: ${data.actualEquity}\n`; - result += `Account Maint. Margin: ${data.accountMaintMargin}\n`; - result += `Account Status: ${data.accountStatus}\n\n`; - - if (data.accountType) { - result += `Account Type: ${data.accountType}\n`; - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin account: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.account({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Account Information\n\n`; + + if (data) { + result += `**Account Status**\n`; + result += `UniMMR: ${data.uniMMR}\n`; + result += `Account Equity: ${data.accountEquity}\n`; + result += `Actual Equity: ${data.actualEquity}\n`; + result += `Account Maint. Margin: ${data.accountMaintMargin}\n`; + result += `Account Status: ${data.accountStatus}\n\n`; + + if (data.accountType) { + result += `Account Type: ${data.accountType}\n`; + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin account: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getBalance.ts b/src/modules/portfolio-margin/account/getBalance.ts index 8a0d771f..885aed98 100644 --- a/src/modules/portfolio-margin/account/getBalance.ts +++ b/src/modules/portfolio-margin/account/getBalance.ts @@ -5,60 +5,72 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getBalance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetBalance(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetBalance", - "Get Portfolio Margin account balance information for all assets.", - { - asset: z.string().optional().describe("Asset to query (e.g., 'USDT'). If not provided, returns all assets"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.balance({ - ...(params.asset && { asset: params.asset }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Balance\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `| Asset | Total | Available | In Order | Borrowed |\n`; - result += `|-------|-------|-----------|----------|----------|\n`; - data.forEach((balance: any) => { - result += `| ${balance.asset} | ${balance.totalWalletBalance || balance.balance} | ${balance.availableBalance || 'N/A'} | ${balance.crossWalletBalance || 'N/A'} | ${balance.borrowed || '0'} |\n`; - }); - } else if (data && !Array.isArray(data)) { - result += `**${data.asset}**\n`; - result += `Total Balance: ${data.totalWalletBalance || data.balance}\n`; - result += `Available: ${data.availableBalance || 'N/A'}\n`; - result += `Borrowed: ${data.borrowed || '0'}\n`; - } else { - result += `No balance information found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin balance: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginGetBalance", + { + description: "Get Portfolio Margin account balance information for all assets.", + inputSchema: { + asset: z + .string() + .optional() + .describe("Asset to query (e.g., 'USDT'). If not provided, returns all assets"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.balance({ + ...(params.asset && { asset: params.asset }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Balance\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `| Asset | Total | Available | In Order | Borrowed |\n`; + result += `|-------|-------|-----------|----------|----------|\n`; + data.forEach((balance: any) => { + result += `| ${balance.asset} | ${balance.totalWalletBalance || balance.balance} | ${balance.availableBalance || "N/A"} | ${balance.crossWalletBalance || "N/A"} | ${balance.borrowed || "0"} |\n`; + }); + } else if (data && !Array.isArray(data)) { + result += `**${data.asset}**\n`; + result += `Total Balance: ${data.totalWalletBalance || data.balance}\n`; + result += `Available: ${data.availableBalance || "N/A"}\n`; + result += `Borrowed: ${data.borrowed || "0"}\n`; + } else { + result += `No balance information found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin balance: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getCmAccount.ts b/src/modules/portfolio-margin/account/getCmAccount.ts index bbff79a5..cdef7e09 100644 --- a/src/modules/portfolio-margin/account/getCmAccount.ts +++ b/src/modules/portfolio-margin/account/getCmAccount.ts @@ -5,65 +5,76 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getCmAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetCmAccount(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetCmAccount", - "Get COIN-M Futures account information within Portfolio Margin mode.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM (COIN-M) Account\n\n`; - - if (data) { - result += `**Account Overview**\n`; - if (data.assets && data.assets.length > 0) { - result += `\n**Assets**\n`; - data.assets.forEach((asset: any) => { - result += `**${asset.asset}**\n`; - result += ` Wallet Balance: ${asset.walletBalance}\n`; - result += ` Unrealized Profit: ${asset.unrealizedProfit}\n`; - result += ` Margin Balance: ${asset.marginBalance}\n`; - result += ` Maint Margin: ${asset.maintMargin}\n`; - result += ` Available Balance: ${asset.availableBalance}\n\n`; - }); - } - - if (data.positions && data.positions.length > 0) { - result += `\n**Positions**\n`; - data.positions.filter((p: any) => parseFloat(p.positionAmt) !== 0).forEach((pos: any) => { - result += `- ${pos.symbol}: ${pos.positionAmt} @ ${pos.entryPrice}\n`; - }); - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM account: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginGetCmAccount", + { + description: "Get COIN-M Futures account information within Portfolio Margin mode.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM (COIN-M) Account\n\n`; + + if (data) { + result += `**Account Overview**\n`; + if (data.assets && data.assets.length > 0) { + result += `\n**Assets**\n`; + data.assets.forEach((asset: any) => { + result += `**${asset.asset}**\n`; + result += ` Wallet Balance: ${asset.walletBalance}\n`; + result += ` Unrealized Profit: ${asset.unrealizedProfit}\n`; + result += ` Margin Balance: ${asset.marginBalance}\n`; + result += ` Maint Margin: ${asset.maintMargin}\n`; + result += ` Available Balance: ${asset.availableBalance}\n\n`; + }); + } + + if (data.positions && data.positions.length > 0) { + result += `\n**Positions**\n`; + data.positions + .filter((p: any) => parseFloat(p.positionAmt) !== 0) + .forEach((pos: any) => { + result += `- ${pos.symbol}: ${pos.positionAmt} @ ${pos.entryPrice}\n`; + }); + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM account: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getCmPosition.ts b/src/modules/portfolio-margin/account/getCmPosition.ts index ef765a9d..33f456e3 100644 --- a/src/modules/portfolio-margin/account/getCmPosition.ts +++ b/src/modules/portfolio-margin/account/getCmPosition.ts @@ -5,69 +5,78 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getCmPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetCmPosition(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetCmPosition", - "Get COIN-M Futures position risk information within Portfolio Margin mode.", - { - marginAsset: z.string().optional().describe("Margin asset (e.g., 'BTC')"), - pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmPositionRisk({ - ...(params.marginAsset && { marginAsset: params.marginAsset }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM Position Risk\n\n`; - - if (Array.isArray(data) && data.length > 0) { - const activePositions = data.filter((p: any) => parseFloat(p.positionAmt) !== 0); - - if (activePositions.length > 0) { - result += `Active Positions: ${activePositions.length}\n\n`; - activePositions.forEach((pos: any) => { - result += `**${pos.symbol}**\n`; - result += ` Position: ${pos.positionAmt} contracts\n`; - result += ` Entry Price: ${pos.entryPrice}\n`; - result += ` Mark Price: ${pos.markPrice}\n`; - result += ` Unrealized PnL: ${pos.unrealizedProfit}\n`; - result += ` Liquidation Price: ${pos.liquidationPrice}\n`; - result += ` Leverage: ${pos.leverage}x\n`; - result += ` Margin Type: ${pos.marginType}\n\n`; - }); - } else { - result += `No active CM positions`; - } - } else { - result += `No position data found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM positions: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginGetCmPosition", + { + description: "Get COIN-M Futures position risk information within Portfolio Margin mode.", + inputSchema: { + marginAsset: z.string().optional().describe("Margin asset (e.g., 'BTC')"), + pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmPositionRisk({ + ...(params.marginAsset && { marginAsset: params.marginAsset }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM Position Risk\n\n`; + + if (Array.isArray(data) && data.length > 0) { + const activePositions = data.filter((p: any) => parseFloat(p.positionAmt) !== 0); + + if (activePositions.length > 0) { + result += `Active Positions: ${activePositions.length}\n\n`; + activePositions.forEach((pos: any) => { + result += `**${pos.symbol}**\n`; + result += ` Position: ${pos.positionAmt} contracts\n`; + result += ` Entry Price: ${pos.entryPrice}\n`; + result += ` Mark Price: ${pos.markPrice}\n`; + result += ` Unrealized PnL: ${pos.unrealizedProfit}\n`; + result += ` Liquidation Price: ${pos.liquidationPrice}\n`; + result += ` Leverage: ${pos.leverage}x\n`; + result += ` Margin Type: ${pos.marginType}\n\n`; + }); + } else { + result += `No active CM positions`; + } + } else { + result += `No position data found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getMarginAccount.ts b/src/modules/portfolio-margin/account/getMarginAccount.ts index 72608034..7f42ca0c 100644 --- a/src/modules/portfolio-margin/account/getMarginAccount.ts +++ b/src/modules/portfolio-margin/account/getMarginAccount.ts @@ -5,70 +5,80 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetMarginAccount(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetMarginAccount", - "Get cross margin account information within Portfolio Margin mode.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin - Cross Margin Account\n\n`; - - if (data) { - result += `**Account Overview**\n`; - result += `Borrow Enabled: ${data.borrowEnabled}\n`; - result += `Trade Enabled: ${data.tradeEnabled}\n`; - result += `Transfer Enabled: ${data.transferEnabled}\n`; - result += `Margin Level: ${data.marginLevel}\n`; - result += `Total Asset (BTC): ${data.totalAssetOfBtc}\n`; - result += `Total Liability (BTC): ${data.totalLiabilityOfBtc}\n`; - result += `Total Net Asset (BTC): ${data.totalNetAssetOfBtc}\n\n`; - - if (data.userAssets && data.userAssets.length > 0) { - result += `**Assets with Balance**\n`; - const assetsWithBalance = data.userAssets.filter((a: any) => - parseFloat(a.free) > 0 || parseFloat(a.locked) > 0 || parseFloat(a.borrowed) > 0 - ); - assetsWithBalance.slice(0, 15).forEach((asset: any) => { - result += `**${asset.asset}**\n`; - result += ` Free: ${asset.free} | Locked: ${asset.locked}\n`; - result += ` Borrowed: ${asset.borrowed} | Interest: ${asset.interest}\n`; - result += ` Net Asset: ${asset.netAsset}\n\n`; - }); - if (assetsWithBalance.length > 15) { - result += `... and ${assetsWithBalance.length - 15} more assets`; - } - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin margin account: ${errorMessage}` - }], - isError: true - }; + server.registerTool( + "BinancePortfolioMarginGetMarginAccount", + { + description: "Get cross margin account information within Portfolio Margin mode.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin - Cross Margin Account\n\n`; + + if (data) { + result += `**Account Overview**\n`; + result += `Borrow Enabled: ${data.borrowEnabled}\n`; + result += `Trade Enabled: ${data.tradeEnabled}\n`; + result += `Transfer Enabled: ${data.transferEnabled}\n`; + result += `Margin Level: ${data.marginLevel}\n`; + result += `Total Asset (BTC): ${data.totalAssetOfBtc}\n`; + result += `Total Liability (BTC): ${data.totalLiabilityOfBtc}\n`; + result += `Total Net Asset (BTC): ${data.totalNetAssetOfBtc}\n\n`; + + if (data.userAssets && data.userAssets.length > 0) { + result += `**Assets with Balance**\n`; + const assetsWithBalance = data.userAssets.filter( + (a: any) => + parseFloat(a.free) > 0 || parseFloat(a.locked) > 0 || parseFloat(a.borrowed) > 0, + ); + assetsWithBalance.slice(0, 15).forEach((asset: any) => { + result += `**${asset.asset}**\n`; + result += ` Free: ${asset.free} | Locked: ${asset.locked}\n`; + result += ` Borrowed: ${asset.borrowed} | Interest: ${asset.interest}\n`; + result += ` Net Asset: ${asset.netAsset}\n\n`; + }); + if (assetsWithBalance.length > 15) { + result += `... and ${assetsWithBalance.length - 15} more assets`; } + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin margin account: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getMaxBorrowable.ts b/src/modules/portfolio-margin/account/getMaxBorrowable.ts index 2bb58887..dd809420 100644 --- a/src/modules/portfolio-margin/account/getMaxBorrowable.ts +++ b/src/modules/portfolio-margin/account/getMaxBorrowable.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getMaxBorrowable.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetMaxBorrowable(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetMaxBorrowable", + server.registerTool( + "BinancePortfolioMarginGetMaxBorrowable", + { + description: "Query the maximum amount that can be borrowed for a specific asset in Portfolio Margin mode.", - { - asset: z.string().describe("Asset to query (e.g., 'USDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginMaxBorrowable({ - asset: params.asset, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Max Borrowable\n\nAsset: ${params.asset}\nMax Borrowable Amount: ${data.amount}\nBorrowed: ${data.borrowedAmount || '0'}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get max borrowable: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + asset: z.string().describe("Asset to query (e.g., 'USDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginMaxBorrowable({ + asset: params.asset, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Max Borrowable\n\nAsset: ${params.asset}\nMax Borrowable Amount: ${data.amount}\nBorrowed: ${data.borrowedAmount || "0"}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get max borrowable: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getMaxWithdraw.ts b/src/modules/portfolio-margin/account/getMaxWithdraw.ts index 858b05e5..afc7d9d8 100644 --- a/src/modules/portfolio-margin/account/getMaxWithdraw.ts +++ b/src/modules/portfolio-margin/account/getMaxWithdraw.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getMaxWithdraw.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetMaxWithdraw(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetMaxWithdraw", + server.registerTool( + "BinancePortfolioMarginGetMaxWithdraw", + { + description: "Query the maximum amount that can be withdrawn for a specific asset from Portfolio Margin account.", - { - asset: z.string().describe("Asset to query (e.g., 'USDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginMaxWithdraw({ - asset: params.asset, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Max Withdraw\n\nAsset: ${params.asset}\nMax Withdraw Amount: ${data.amount}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get max withdraw: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + asset: z.string().describe("Asset to query (e.g., 'USDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginMaxWithdraw({ + asset: params.asset, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Max Withdraw\n\nAsset: ${params.asset}\nMax Withdraw Amount: ${data.amount}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get max withdraw: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getUmAccount.ts b/src/modules/portfolio-margin/account/getUmAccount.ts index 946160a3..c3ac2e88 100644 --- a/src/modules/portfolio-margin/account/getUmAccount.ts +++ b/src/modules/portfolio-margin/account/getUmAccount.ts @@ -5,62 +5,71 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getUmAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetUmAccount(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetUmAccount", - "Get USDT-M Futures account information within Portfolio Margin mode.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM (USDT-M) Account\n\n`; - - if (data) { - result += `**Account Overview**\n`; - result += `Total Wallet Balance: ${data.totalWalletBalance}\n`; - result += `Total Unrealized Profit: ${data.totalUnrealizedProfit}\n`; - result += `Total Margin Balance: ${data.totalMarginBalance}\n`; - result += `Total Position Initial Margin: ${data.totalPositionInitialMargin}\n`; - result += `Total Open Order Initial Margin: ${data.totalOpenOrderInitialMargin}\n`; - result += `Total Cross Wallet Balance: ${data.totalCrossWalletBalance}\n`; - result += `Available Balance: ${data.availableBalance}\n`; - result += `Max Withdraw Amount: ${data.maxWithdrawAmount}\n\n`; - - if (data.assets && data.assets.length > 0) { - result += `**Assets**\n`; - data.assets.slice(0, 10).forEach((asset: any) => { - result += `- ${asset.asset}: Balance ${asset.walletBalance}, Available ${asset.availableBalance}\n`; - }); - } - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM account: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginGetUmAccount", + { + description: "Get USDT-M Futures account information within Portfolio Margin mode.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM (USDT-M) Account\n\n`; + + if (data) { + result += `**Account Overview**\n`; + result += `Total Wallet Balance: ${data.totalWalletBalance}\n`; + result += `Total Unrealized Profit: ${data.totalUnrealizedProfit}\n`; + result += `Total Margin Balance: ${data.totalMarginBalance}\n`; + result += `Total Position Initial Margin: ${data.totalPositionInitialMargin}\n`; + result += `Total Open Order Initial Margin: ${data.totalOpenOrderInitialMargin}\n`; + result += `Total Cross Wallet Balance: ${data.totalCrossWalletBalance}\n`; + result += `Available Balance: ${data.availableBalance}\n`; + result += `Max Withdraw Amount: ${data.maxWithdrawAmount}\n\n`; + + if (data.assets && data.assets.length > 0) { + result += `**Assets**\n`; + data.assets.slice(0, 10).forEach((asset: any) => { + result += `- ${asset.asset}: Balance ${asset.walletBalance}, Available ${asset.availableBalance}\n`; + }); + } } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM account: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/getUmPosition.ts b/src/modules/portfolio-margin/account/getUmPosition.ts index 75d57e7a..b2afb700 100644 --- a/src/modules/portfolio-margin/account/getUmPosition.ts +++ b/src/modules/portfolio-margin/account/getUmPosition.ts @@ -5,67 +5,76 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/getUmPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginGetUmPosition(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetUmPosition", - "Get USDT-M Futures position risk information within Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umPositionRisk({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM Position Risk\n\n`; - - if (Array.isArray(data) && data.length > 0) { - const activePositions = data.filter((p: any) => parseFloat(p.positionAmt) !== 0); - - if (activePositions.length > 0) { - result += `Active Positions: ${activePositions.length}\n\n`; - activePositions.forEach((pos: any) => { - result += `**${pos.symbol}**\n`; - result += ` Position: ${pos.positionAmt}\n`; - result += ` Entry Price: ${pos.entryPrice}\n`; - result += ` Mark Price: ${pos.markPrice}\n`; - result += ` Unrealized PnL: ${pos.unrealizedProfit}\n`; - result += ` Liquidation Price: ${pos.liquidationPrice}\n`; - result += ` Leverage: ${pos.leverage}x\n`; - result += ` Margin Type: ${pos.marginType}\n\n`; - }); - } else { - result += `No active UM positions`; - } - } else { - result += `No position data found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM positions: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginGetUmPosition", + { + description: "Get USDT-M Futures position risk information within Portfolio Margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umPositionRisk({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM Position Risk\n\n`; + + if (Array.isArray(data) && data.length > 0) { + const activePositions = data.filter((p: any) => parseFloat(p.positionAmt) !== 0); + + if (activePositions.length > 0) { + result += `Active Positions: ${activePositions.length}\n\n`; + activePositions.forEach((pos: any) => { + result += `**${pos.symbol}**\n`; + result += ` Position: ${pos.positionAmt}\n`; + result += ` Entry Price: ${pos.entryPrice}\n`; + result += ` Mark Price: ${pos.markPrice}\n`; + result += ` Unrealized PnL: ${pos.unrealizedProfit}\n`; + result += ` Liquidation Price: ${pos.liquidationPrice}\n`; + result += ` Leverage: ${pos.leverage}x\n`; + result += ` Margin Type: ${pos.marginType}\n\n`; + }); + } else { + result += `No active UM positions`; + } + } else { + result += `No position data found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/account/index.ts b/src/modules/portfolio-margin/account/index.ts index c2d89b87..1e96762c 100644 --- a/src/modules/portfolio-margin/account/index.ts +++ b/src/modules/portfolio-margin/account/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/account/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerPortfolioMarginGetAccountInfo } from "./getAccountInfo.js"; import { registerPortfolioMarginGetBalance } from "./getBalance.js"; +import { registerPortfolioMarginGetCmAccount } from "./getCmAccount.js"; +import { registerPortfolioMarginGetCmPosition } from "./getCmPosition.js"; +import { registerPortfolioMarginGetMarginAccount } from "./getMarginAccount.js"; import { registerPortfolioMarginGetMaxBorrowable } from "./getMaxBorrowable.js"; import { registerPortfolioMarginGetMaxWithdraw } from "./getMaxWithdraw.js"; import { registerPortfolioMarginGetUmAccount } from "./getUmAccount.js"; -import { registerPortfolioMarginGetCmAccount } from "./getCmAccount.js"; import { registerPortfolioMarginGetUmPosition } from "./getUmPosition.js"; -import { registerPortfolioMarginGetCmPosition } from "./getCmPosition.js"; -import { registerPortfolioMarginGetMarginAccount } from "./getMarginAccount.js"; export function registerPortfolioMarginAccountApi(server: McpServer) { - registerPortfolioMarginGetAccountInfo(server); - registerPortfolioMarginGetBalance(server); - registerPortfolioMarginGetMaxBorrowable(server); - registerPortfolioMarginGetMaxWithdraw(server); - registerPortfolioMarginGetUmAccount(server); - registerPortfolioMarginGetCmAccount(server); - registerPortfolioMarginGetUmPosition(server); - registerPortfolioMarginGetCmPosition(server); - registerPortfolioMarginGetMarginAccount(server); + registerPortfolioMarginGetAccountInfo(server); + registerPortfolioMarginGetBalance(server); + registerPortfolioMarginGetMaxBorrowable(server); + registerPortfolioMarginGetMaxWithdraw(server); + registerPortfolioMarginGetUmAccount(server); + registerPortfolioMarginGetCmAccount(server); + registerPortfolioMarginGetUmPosition(server); + registerPortfolioMarginGetCmPosition(server); + registerPortfolioMarginGetMarginAccount(server); } diff --git a/src/modules/portfolio-margin/cm-trade/cancelAllOrders.ts b/src/modules/portfolio-margin/cm-trade/cancelAllOrders.ts index d4f6c727..98f57f5c 100644 --- a/src/modules/portfolio-margin/cm-trade/cancelAllOrders.ts +++ b/src/modules/portfolio-margin/cm-trade/cancelAllOrders.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmCancelAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmCancelAllOrders", + server.registerTool( + "BinancePortfolioMarginCmCancelAllOrders", + { + description: "Cancel all open COIN-M Futures orders for a symbol in Portfolio Margin mode. ⚠️ This will cancel ALL open orders.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmCancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All Portfolio Margin CM orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel all Portfolio Margin CM orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmCancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ All Portfolio Margin CM orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel all Portfolio Margin CM orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/cancelOrder.ts b/src/modules/portfolio-margin/cm-trade/cancelOrder.ts index 8621e751..aee5bc81 100644 --- a/src/modules/portfolio-margin/cm-trade/cancelOrder.ts +++ b/src/modules/portfolio-margin/cm-trade/cancelOrder.ts @@ -5,57 +5,68 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmCancelOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmCancelOrder", - "Cancel an active COIN-M Futures order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.cmCancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin CM Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel Portfolio Margin CM order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginCmCancelOrder", + { + description: "Cancel an active COIN-M Futures order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.cmCancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin CM Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel Portfolio Margin CM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/changeLeverage.ts b/src/modules/portfolio-margin/cm-trade/changeLeverage.ts index e73e2332..da0c82da 100644 --- a/src/modules/portfolio-margin/cm-trade/changeLeverage.ts +++ b/src/modules/portfolio-margin/cm-trade/changeLeverage.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/changeLeverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmChangeLeverage(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmChangeLeverage", + server.registerTool( + "BinancePortfolioMarginCmChangeLeverage", + { + description: "Change leverage for a COIN-M Futures symbol in Portfolio Margin mode. ⚠️ Higher leverage increases risk.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin CM Leverage Changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Qty: ${data.maxQty}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to change Portfolio Margin CM leverage: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmLeverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin CM Leverage Changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Qty: ${data.maxQty}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to change Portfolio Margin CM leverage: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/changeMarginType.ts b/src/modules/portfolio-margin/cm-trade/changeMarginType.ts index 22c122c5..c1311646 100644 --- a/src/modules/portfolio-margin/cm-trade/changeMarginType.ts +++ b/src/modules/portfolio-margin/cm-trade/changeMarginType.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/changeMarginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmChangeMarginType(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmChangeMarginType", + server.registerTool( + "BinancePortfolioMarginCmChangeMarginType", + { + description: "Change margin type (ISOLATED/CROSSED) for a COIN-M Futures symbol in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmMarginType({ - symbol: params.symbol, - marginType: params.marginType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin CM Margin Type Changed!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to change Portfolio Margin CM margin type: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmMarginType({ + symbol: params.symbol, + marginType: params.marginType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin CM Margin Type Changed!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to change Portfolio Margin CM margin type: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/getAllOrders.ts b/src/modules/portfolio-margin/cm-trade/getAllOrders.ts index f99f911c..0548c032 100644 --- a/src/modules/portfolio-margin/cm-trade/getAllOrders.ts +++ b/src/modules/portfolio-margin/cm-trade/getAllOrders.ts @@ -5,71 +5,87 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/getAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmGetAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmGetAllOrders", + server.registerTool( + "BinancePortfolioMarginCmGetAllOrders", + { + description: "Get all COIN-M Futures orders (active, cancelled, filled) in Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of orders to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmAllOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM All Orders\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total orders: ${data.length}\n\n`; - data.slice(0, 20).forEach((order: any, index: number) => { - result += `**${index + 1}. ${order.symbol}**\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more orders`; - } - } else { - result += `No orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM orders: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of orders to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmAllOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM All Orders\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total orders: ${data.length}\n\n`; + data.slice(0, 20).forEach((order: any, index: number) => { + result += `**${index + 1}. ${order.symbol}**\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more orders`; + } + } else { + result += `No orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/getOpenOrders.ts b/src/modules/portfolio-margin/cm-trade/getOpenOrders.ts index ff119842..2f022c6e 100644 --- a/src/modules/portfolio-margin/cm-trade/getOpenOrders.ts +++ b/src/modules/portfolio-margin/cm-trade/getOpenOrders.ts @@ -5,61 +5,70 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmGetOpenOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmGetOpenOrders", - "Get all open COIN-M Futures orders in Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol to filter by"), - pair: z.string().optional().describe("Trading pair to filter by (e.g., 'BTCUSD')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM Open Orders\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total open orders: ${data.length}\n\n`; - data.forEach((order: any, index: number) => { - result += `**${index + 1}. ${order.symbol}**\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty}\n`; - result += ` Status: ${order.status}\n\n`; - }); - } else { - result += `No open orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM open orders: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginCmGetOpenOrders", + { + description: "Get all open COIN-M Futures orders in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol to filter by"), + pair: z.string().optional().describe("Trading pair to filter by (e.g., 'BTCUSD')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM Open Orders\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total open orders: ${data.length}\n\n`; + data.forEach((order: any, index: number) => { + result += `**${index + 1}. ${order.symbol}**\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty}\n`; + result += ` Status: ${order.status}\n\n`; + }); + } else { + result += `No open orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM open orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/getOrder.ts b/src/modules/portfolio-margin/cm-trade/getOrder.ts index 3b321c8e..a41c90e2 100644 --- a/src/modules/portfolio-margin/cm-trade/getOrder.ts +++ b/src/modules/portfolio-margin/cm-trade/getOrder.ts @@ -5,67 +5,78 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmGetOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmGetOrder", - "Query a specific COIN-M Futures order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - orderId: z.number().int().optional().describe("Order ID to query"), - origClientOrderId: z.string().optional().describe("Original client order ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.cmOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM Order Details\n\n`; - result += `Order ID: ${data.orderId}\n`; - result += `Symbol: ${data.symbol}\n`; - result += `Side: ${data.side} | Type: ${data.type}\n`; - result += `Price: ${data.price} | Qty: ${data.origQty}\n`; - result += `Executed Qty: ${data.executedQty}\n`; - result += `Avg Price: ${data.avgPrice}\n`; - result += `Status: ${data.status}\n`; - result += `Time: ${new Date(data.time).toISOString()}`; - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginCmGetOrder", + { + description: "Query a specific COIN-M Futures order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + orderId: z.number().int().optional().describe("Order ID to query"), + origClientOrderId: z.string().optional().describe("Original client order ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.cmOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM Order Details\n\n`; + result += `Order ID: ${data.orderId}\n`; + result += `Symbol: ${data.symbol}\n`; + result += `Side: ${data.side} | Type: ${data.type}\n`; + result += `Price: ${data.price} | Qty: ${data.origQty}\n`; + result += `Executed Qty: ${data.executedQty}\n`; + result += `Avg Price: ${data.avgPrice}\n`; + result += `Status: ${data.status}\n`; + result += `Time: ${new Date(data.time).toISOString()}`; + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/getUserTrades.ts b/src/modules/portfolio-margin/cm-trade/getUserTrades.ts index c9b9b41c..f42e5ef6 100644 --- a/src/modules/portfolio-margin/cm-trade/getUserTrades.ts +++ b/src/modules/portfolio-margin/cm-trade/getUserTrades.ts @@ -5,74 +5,89 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/getUserTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmGetUserTrades(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmGetUserTrades", - "Get COIN-M Futures trade history in Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of trades to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmUserTrades({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin CM Trade History\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - result += `**${index + 1}. ${trade.symbol}**\n`; - result += ` Trade ID: ${trade.id}\n`; - result += ` Order ID: ${trade.orderId}\n`; - result += ` Side: ${trade.side} | Price: ${trade.price}\n`; - result += ` Qty: ${trade.qty} | Base Qty: ${trade.baseQty}\n`; - result += ` Realized PnL: ${trade.realizedPnl}\n`; - result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; - result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more trades`; - } - } else { - result += `No trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin CM trades: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginCmGetUserTrades", + { + description: "Get COIN-M Futures trade history in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + pair: z.string().optional().describe("Trading pair (e.g., 'BTCUSD')"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of trades to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmUserTrades({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin CM Trade History\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + result += `**${index + 1}. ${trade.symbol}**\n`; + result += ` Trade ID: ${trade.id}\n`; + result += ` Order ID: ${trade.orderId}\n`; + result += ` Side: ${trade.side} | Price: ${trade.price}\n`; + result += ` Qty: ${trade.qty} | Base Qty: ${trade.baseQty}\n`; + result += ` Realized PnL: ${trade.realizedPnl}\n`; + result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; + result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more trades`; + } + } else { + result += `No trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin CM trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/cm-trade/index.ts b/src/modules/portfolio-margin/cm-trade/index.ts index 690498ca..3105bbf5 100644 --- a/src/modules/portfolio-margin/cm-trade/index.ts +++ b/src/modules/portfolio-margin/cm-trade/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerPortfolioMarginCmNewOrder } from "./newOrder.js"; -import { registerPortfolioMarginCmCancelOrder } from "./cancelOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerPortfolioMarginCmCancelAllOrders } from "./cancelAllOrders.js"; -import { registerPortfolioMarginCmGetOrder } from "./getOrder.js"; +import { registerPortfolioMarginCmCancelOrder } from "./cancelOrder.js"; +import { registerPortfolioMarginCmChangeLeverage } from "./changeLeverage.js"; +import { registerPortfolioMarginCmChangeMarginType } from "./changeMarginType.js"; import { registerPortfolioMarginCmGetAllOrders } from "./getAllOrders.js"; import { registerPortfolioMarginCmGetOpenOrders } from "./getOpenOrders.js"; +import { registerPortfolioMarginCmGetOrder } from "./getOrder.js"; import { registerPortfolioMarginCmGetUserTrades } from "./getUserTrades.js"; -import { registerPortfolioMarginCmChangeLeverage } from "./changeLeverage.js"; -import { registerPortfolioMarginCmChangeMarginType } from "./changeMarginType.js"; +import { registerPortfolioMarginCmNewOrder } from "./newOrder.js"; export function registerPortfolioMarginCmTradeApi(server: McpServer) { - registerPortfolioMarginCmNewOrder(server); - registerPortfolioMarginCmCancelOrder(server); - registerPortfolioMarginCmCancelAllOrders(server); - registerPortfolioMarginCmGetOrder(server); - registerPortfolioMarginCmGetAllOrders(server); - registerPortfolioMarginCmGetOpenOrders(server); - registerPortfolioMarginCmGetUserTrades(server); - registerPortfolioMarginCmChangeLeverage(server); - registerPortfolioMarginCmChangeMarginType(server); + registerPortfolioMarginCmNewOrder(server); + registerPortfolioMarginCmCancelOrder(server); + registerPortfolioMarginCmCancelAllOrders(server); + registerPortfolioMarginCmGetOrder(server); + registerPortfolioMarginCmGetAllOrders(server); + registerPortfolioMarginCmGetOpenOrders(server); + registerPortfolioMarginCmGetUserTrades(server); + registerPortfolioMarginCmChangeLeverage(server); + registerPortfolioMarginCmChangeMarginType(server); } diff --git a/src/modules/portfolio-margin/cm-trade/newOrder.ts b/src/modules/portfolio-margin/cm-trade/newOrder.ts index 1474e9e4..e0835fbb 100644 --- a/src/modules/portfolio-margin/cm-trade/newOrder.ts +++ b/src/modules/portfolio-margin/cm-trade/newOrder.ts @@ -5,62 +5,84 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/cm-trade/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginCmNewOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginCmNewOrder", + server.registerTool( + "BinancePortfolioMarginCmNewOrder", + { + description: "Place a new COIN-M Futures order in Portfolio Margin mode. ⚠️ HIGH RISK: Futures trading involves leverage.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"]) - .describe("Order type"), - quantity: z.string().optional().describe("Order quantity in contracts"), - price: z.string().optional().describe("Limit price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), - reduceOnly: z.boolean().optional().describe("Reduce position only"), - newClientOrderId: z.string().optional().describe("Custom client order ID"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for hedge mode"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.cmNewOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin CM Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || 'MARKET'}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place Portfolio Margin CM order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSD_PERP')"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity in contracts"), + price: z.string().optional().describe("Limit price (required for LIMIT orders)"), + stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), + reduceOnly: z.boolean().optional().describe("Reduce position only"), + newClientOrderId: z.string().optional().describe("Custom client order ID"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for hedge mode"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.cmNewOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin CM Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || "MARKET"}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place Portfolio Margin CM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/index.ts b/src/modules/portfolio-margin/index.ts index a808a195..a99301c4 100644 --- a/src/modules/portfolio-margin/index.ts +++ b/src/modules/portfolio-margin/index.ts @@ -1,7 +1,8 @@ // src/modules/portfolio-margin/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinancePortfolioMarginTools } from "../../tools/binance-portfolio-margin/index.js"; export function registerPortfolioMargin(server: McpServer) { - registerBinancePortfolioMarginTools(server); + registerBinancePortfolioMarginTools(server); } diff --git a/src/modules/portfolio-margin/margin-trade/cancelAllOrders.ts b/src/modules/portfolio-margin/margin-trade/cancelAllOrders.ts index e40106c8..e6352c5c 100644 --- a/src/modules/portfolio-margin/margin-trade/cancelAllOrders.ts +++ b/src/modules/portfolio-margin/margin-trade/cancelAllOrders.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginCancelAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginCancelAllOrders", + server.registerTool( + "BinancePortfolioMarginMarginCancelAllOrders", + { + description: "Cancel all open cross margin orders for a symbol in Portfolio Margin mode. ⚠️ This will cancel ALL open orders.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginCancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All Portfolio Margin margin orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel all Portfolio Margin margin orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginCancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ All Portfolio Margin margin orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel all Portfolio Margin margin orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/cancelOrder.ts b/src/modules/portfolio-margin/margin-trade/cancelOrder.ts index 5a9a9e88..e2f67b37 100644 --- a/src/modules/portfolio-margin/margin-trade/cancelOrder.ts +++ b/src/modules/portfolio-margin/margin-trade/cancelOrder.ts @@ -5,57 +5,68 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginCancelOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginCancelOrder", - "Cancel an active cross margin order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.marginCancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Margin Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel Portfolio Margin margin order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginMarginCancelOrder", + { + description: "Cancel an active cross margin order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.marginCancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Margin Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel Portfolio Margin margin order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/getAllOrders.ts b/src/modules/portfolio-margin/margin-trade/getAllOrders.ts index d6636d7e..f499669b 100644 --- a/src/modules/portfolio-margin/margin-trade/getAllOrders.ts +++ b/src/modules/portfolio-margin/margin-trade/getAllOrders.ts @@ -5,68 +5,84 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/getAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginGetAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginGetAllOrders", + server.registerTool( + "BinancePortfolioMarginMarginGetAllOrders", + { + description: "Get all cross margin orders (active, cancelled, filled) in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(500).optional().describe("Number of orders to return (default 500, max 500)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginAllOrders({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Margin All Orders - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total orders: ${data.length}\n\n`; - data.slice(0, 20).forEach((order: any, index: number) => { - result += `**${index + 1}. Order ID: ${order.orderId}**\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more orders`; - } - } else { - result += `No orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin margin orders: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(500) + .optional() + .describe("Number of orders to return (default 500, max 500)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginAllOrders({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Margin All Orders - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total orders: ${data.length}\n\n`; + data.slice(0, 20).forEach((order: any, index: number) => { + result += `**${index + 1}. Order ID: ${order.orderId}**\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more orders`; + } + } else { + result += `No orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin margin orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/getOpenOrders.ts b/src/modules/portfolio-margin/margin-trade/getOpenOrders.ts index 02359040..c0054ddb 100644 --- a/src/modules/portfolio-margin/margin-trade/getOpenOrders.ts +++ b/src/modules/portfolio-margin/margin-trade/getOpenOrders.ts @@ -5,59 +5,68 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginGetOpenOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginGetOpenOrders", - "Get all open cross margin orders in Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol to filter by"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Margin Open Orders\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total open orders: ${data.length}\n\n`; - data.forEach((order: any, index: number) => { - result += `**${index + 1}. ${order.symbol}**\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty}\n`; - result += ` Status: ${order.status}\n\n`; - }); - } else { - result += `No open orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin margin open orders: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginMarginGetOpenOrders", + { + description: "Get all open cross margin orders in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol to filter by"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Margin Open Orders\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total open orders: ${data.length}\n\n`; + data.forEach((order: any, index: number) => { + result += `**${index + 1}. ${order.symbol}**\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty}\n`; + result += ` Status: ${order.status}\n\n`; + }); + } else { + result += `No open orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin margin open orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/getOrder.ts b/src/modules/portfolio-margin/margin-trade/getOrder.ts index b3ba8195..33660a06 100644 --- a/src/modules/portfolio-margin/margin-trade/getOrder.ts +++ b/src/modules/portfolio-margin/margin-trade/getOrder.ts @@ -5,66 +5,77 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginGetOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginGetOrder", - "Query a specific cross margin order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to query"), - origClientOrderId: z.string().optional().describe("Original client order ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.marginOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Margin Order Details\n\n`; - result += `Order ID: ${data.orderId}\n`; - result += `Symbol: ${data.symbol}\n`; - result += `Side: ${data.side} | Type: ${data.type}\n`; - result += `Price: ${data.price} | Qty: ${data.origQty}\n`; - result += `Executed Qty: ${data.executedQty}\n`; - result += `Status: ${data.status}\n`; - result += `Time: ${new Date(data.time).toISOString()}`; - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin margin order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginMarginGetOrder", + { + description: "Query a specific cross margin order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to query"), + origClientOrderId: z.string().optional().describe("Original client order ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.marginOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Margin Order Details\n\n`; + result += `Order ID: ${data.orderId}\n`; + result += `Symbol: ${data.symbol}\n`; + result += `Side: ${data.side} | Type: ${data.type}\n`; + result += `Price: ${data.price} | Qty: ${data.origQty}\n`; + result += `Executed Qty: ${data.executedQty}\n`; + result += `Status: ${data.status}\n`; + result += `Time: ${new Date(data.time).toISOString()}`; + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin margin order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/getUserTrades.ts b/src/modules/portfolio-margin/margin-trade/getUserTrades.ts index 48a85705..48b976ee 100644 --- a/src/modules/portfolio-margin/margin-trade/getUserTrades.ts +++ b/src/modules/portfolio-margin/margin-trade/getUserTrades.ts @@ -5,71 +5,86 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/getUserTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginGetUserTrades(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginGetUserTrades", - "Get cross margin trade history in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of trades to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginMyTrades({ - symbol: params.symbol, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin Margin Trade History - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - result += `**${index + 1}. Trade ID: ${trade.id}**\n`; - result += ` Order ID: ${trade.orderId}\n`; - result += ` Price: ${trade.price} | Qty: ${trade.qty}\n`; - result += ` Quote Qty: ${trade.quoteQty}\n`; - result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; - result += ` Is Buyer: ${trade.isBuyer} | Is Maker: ${trade.isMaker}\n`; - result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more trades`; - } - } else { - result += `No trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin margin trades: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginMarginGetUserTrades", + { + description: "Get cross margin trade history in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of trades to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginMyTrades({ + symbol: params.symbol, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin Margin Trade History - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + result += `**${index + 1}. Trade ID: ${trade.id}**\n`; + result += ` Order ID: ${trade.orderId}\n`; + result += ` Price: ${trade.price} | Qty: ${trade.qty}\n`; + result += ` Quote Qty: ${trade.quoteQty}\n`; + result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; + result += ` Is Buyer: ${trade.isBuyer} | Is Maker: ${trade.isMaker}\n`; + result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more trades`; + } + } else { + result += `No trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin margin trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/index.ts b/src/modules/portfolio-margin/margin-trade/index.ts index c6293d1d..d4c4baed 100644 --- a/src/modules/portfolio-margin/margin-trade/index.ts +++ b/src/modules/portfolio-margin/margin-trade/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerPortfolioMarginMarginNewOrder } from "./newOrder.js"; -import { registerPortfolioMarginMarginCancelOrder } from "./cancelOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerPortfolioMarginMarginCancelAllOrders } from "./cancelAllOrders.js"; -import { registerPortfolioMarginMarginGetOrder } from "./getOrder.js"; +import { registerPortfolioMarginMarginCancelOrder } from "./cancelOrder.js"; import { registerPortfolioMarginMarginGetAllOrders } from "./getAllOrders.js"; import { registerPortfolioMarginMarginGetOpenOrders } from "./getOpenOrders.js"; +import { registerPortfolioMarginMarginGetOrder } from "./getOrder.js"; +import { registerPortfolioMarginMarginGetUserTrades } from "./getUserTrades.js"; import { registerPortfolioMarginMarginLoan } from "./marginLoan.js"; import { registerPortfolioMarginMarginRepay } from "./marginRepay.js"; -import { registerPortfolioMarginMarginGetUserTrades } from "./getUserTrades.js"; +import { registerPortfolioMarginMarginNewOrder } from "./newOrder.js"; export function registerPortfolioMarginMarginTradeApi(server: McpServer) { - registerPortfolioMarginMarginNewOrder(server); - registerPortfolioMarginMarginCancelOrder(server); - registerPortfolioMarginMarginCancelAllOrders(server); - registerPortfolioMarginMarginGetOrder(server); - registerPortfolioMarginMarginGetAllOrders(server); - registerPortfolioMarginMarginGetOpenOrders(server); - registerPortfolioMarginMarginLoan(server); - registerPortfolioMarginMarginRepay(server); - registerPortfolioMarginMarginGetUserTrades(server); + registerPortfolioMarginMarginNewOrder(server); + registerPortfolioMarginMarginCancelOrder(server); + registerPortfolioMarginMarginCancelAllOrders(server); + registerPortfolioMarginMarginGetOrder(server); + registerPortfolioMarginMarginGetAllOrders(server); + registerPortfolioMarginMarginGetOpenOrders(server); + registerPortfolioMarginMarginLoan(server); + registerPortfolioMarginMarginRepay(server); + registerPortfolioMarginMarginGetUserTrades(server); } diff --git a/src/modules/portfolio-margin/margin-trade/marginLoan.ts b/src/modules/portfolio-margin/margin-trade/marginLoan.ts index f893f9bb..e3d7f410 100644 --- a/src/modules/portfolio-margin/margin-trade/marginLoan.ts +++ b/src/modules/portfolio-margin/margin-trade/marginLoan.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/marginLoan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginLoan(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginLoan", + server.registerTool( + "BinancePortfolioMarginMarginLoan", + { + description: "Borrow funds for margin trading in Portfolio Margin mode. ⚠️ Borrowed funds accrue interest.", - { - asset: z.string().describe("Asset to borrow (e.g., 'USDT')"), - amount: z.string().describe("Amount to borrow"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginLoan({ - asset: params.asset, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Loan Successful!\n\nTransaction ID: ${data.tranId}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\n⚠️ Note: Borrowed funds will accrue interest.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to borrow funds: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + asset: z.string().describe("Asset to borrow (e.g., 'USDT')"), + amount: z.string().describe("Amount to borrow"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginLoan({ + asset: params.asset, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Loan Successful!\n\nTransaction ID: ${data.tranId}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\n⚠️ Note: Borrowed funds will accrue interest.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to borrow funds: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/marginRepay.ts b/src/modules/portfolio-margin/margin-trade/marginRepay.ts index 06600ce2..102346ff 100644 --- a/src/modules/portfolio-margin/margin-trade/marginRepay.ts +++ b/src/modules/portfolio-margin/margin-trade/marginRepay.ts @@ -5,45 +5,54 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/marginRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginRepay(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginRepay", - "Repay borrowed funds in Portfolio Margin mode.", - { - asset: z.string().describe("Asset to repay (e.g., 'USDT')"), - amount: z.string().describe("Amount to repay"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginRepay({ - asset: params.asset, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Repayment Successful!\n\nTransaction ID: ${data.tranId}\nAsset: ${params.asset}\nAmount: ${params.amount}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to repay funds: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinancePortfolioMarginMarginRepay", + { + description: "Repay borrowed funds in Portfolio Margin mode.", + inputSchema: { + asset: z.string().describe("Asset to repay (e.g., 'USDT')"), + amount: z.string().describe("Amount to repay"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginRepay({ + asset: params.asset, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Repayment Successful!\n\nTransaction ID: ${data.tranId}\nAsset: ${params.asset}\nAmount: ${params.amount}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to repay funds: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/margin-trade/newOrder.ts b/src/modules/portfolio-margin/margin-trade/newOrder.ts index 14e031c4..65ed229c 100644 --- a/src/modules/portfolio-margin/margin-trade/newOrder.ts +++ b/src/modules/portfolio-margin/margin-trade/newOrder.ts @@ -5,63 +5,84 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/margin-trade/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginMarginNewOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginMarginNewOrder", + server.registerTool( + "BinancePortfolioMarginMarginNewOrder", + { + description: "Place a new cross margin order in Portfolio Margin mode. ⚠️ Margin trading involves borrowing and interest.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]) - .describe("Order type"), - quantity: z.string().optional().describe("Order quantity"), - quoteOrderQty: z.string().optional().describe("Quote quantity (for MARKET orders)"), - price: z.string().optional().describe("Limit price"), - stopPrice: z.string().optional().describe("Stop price"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - newClientOrderId: z.string().optional().describe("Custom client order ID"), - sideEffectType: z.enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]).optional() - .describe("Side effect type for margin orders"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.marginNewOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.quantity && { quantity: params.quantity }), - ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Margin Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || 'MARKET'}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place Portfolio Margin margin order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity"), + quoteOrderQty: z.string().optional().describe("Quote quantity (for MARKET orders)"), + price: z.string().optional().describe("Limit price"), + stopPrice: z.string().optional().describe("Stop price"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + newClientOrderId: z.string().optional().describe("Custom client order ID"), + sideEffectType: z + .enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]) + .optional() + .describe("Side effect type for margin orders"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.marginNewOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.quantity && { quantity: params.quantity }), + ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Margin Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || "MARKET"}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place Portfolio Margin margin order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/cancelAllOrders.ts b/src/modules/portfolio-margin/um-trade/cancelAllOrders.ts index d67a13dc..63f3e420 100644 --- a/src/modules/portfolio-margin/um-trade/cancelAllOrders.ts +++ b/src/modules/portfolio-margin/um-trade/cancelAllOrders.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmCancelAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmCancelAllOrders", + server.registerTool( + "BinancePortfolioMarginUmCancelAllOrders", + { + description: "Cancel all open USDT-M Futures orders for a symbol in Portfolio Margin mode. ⚠️ This will cancel ALL open orders.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umCancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All Portfolio Margin UM orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel all Portfolio Margin UM orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umCancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ All Portfolio Margin UM orders cancelled for ${params.symbol}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel all Portfolio Margin UM orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/cancelOrder.ts b/src/modules/portfolio-margin/um-trade/cancelOrder.ts index 0656a949..71443165 100644 --- a/src/modules/portfolio-margin/um-trade/cancelOrder.ts +++ b/src/modules/portfolio-margin/um-trade/cancelOrder.ts @@ -5,57 +5,68 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmCancelOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmCancelOrder", - "Cancel an active USDT-M Futures order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.umCancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin UM Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to cancel Portfolio Margin UM order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginUmCancelOrder", + { + description: "Cancel an active USDT-M Futures order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.umCancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin UM Order Cancelled!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel Portfolio Margin UM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/changeLeverage.ts b/src/modules/portfolio-margin/um-trade/changeLeverage.ts index e0cd3c52..9d46ed31 100644 --- a/src/modules/portfolio-margin/um-trade/changeLeverage.ts +++ b/src/modules/portfolio-margin/um-trade/changeLeverage.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/changeLeverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmChangeLeverage(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmChangeLeverage", + server.registerTool( + "BinancePortfolioMarginUmChangeLeverage", + { + description: "Change leverage for a USDT-M Futures symbol in Portfolio Margin mode. ⚠️ Higher leverage increases risk.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin UM Leverage Changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to change Portfolio Margin UM leverage: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umLeverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin UM Leverage Changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to change Portfolio Margin UM leverage: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/changeMarginType.ts b/src/modules/portfolio-margin/um-trade/changeMarginType.ts index 587ef418..49a66e86 100644 --- a/src/modules/portfolio-margin/um-trade/changeMarginType.ts +++ b/src/modules/portfolio-margin/um-trade/changeMarginType.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/changeMarginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmChangeMarginType(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmChangeMarginType", + server.registerTool( + "BinancePortfolioMarginUmChangeMarginType", + { + description: "Change margin type (ISOLATED/CROSSED) for a USDT-M Futures symbol in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umMarginType({ - symbol: params.symbol, - marginType: params.marginType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin UM Margin Type Changed!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to change Portfolio Margin UM margin type: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umMarginType({ + symbol: params.symbol, + marginType: params.marginType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin UM Margin Type Changed!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to change Portfolio Margin UM margin type: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/getAllOrders.ts b/src/modules/portfolio-margin/um-trade/getAllOrders.ts index c3db2be6..aac202cb 100644 --- a/src/modules/portfolio-margin/um-trade/getAllOrders.ts +++ b/src/modules/portfolio-margin/um-trade/getAllOrders.ts @@ -5,68 +5,84 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/getAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmGetAllOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmGetAllOrders", + server.registerTool( + "BinancePortfolioMarginUmGetAllOrders", + { + description: "Get all USDT-M Futures orders (active, cancelled, filled) in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of orders to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umAllOrders({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM All Orders - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total orders: ${data.length}\n\n`; - data.slice(0, 20).forEach((order: any, index: number) => { - result += `**${index + 1}. Order ID: ${order.orderId}**\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more orders`; - } - } else { - result += `No orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM orders: ${errorMessage}` - }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of orders to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umAllOrders({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM All Orders - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total orders: ${data.length}\n\n`; + data.slice(0, 20).forEach((order: any, index: number) => { + result += `**${index + 1}. Order ID: ${order.orderId}**\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty} | Status: ${order.status}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more orders`; + } + } else { + result += `No orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/getOpenOrders.ts b/src/modules/portfolio-margin/um-trade/getOpenOrders.ts index bbd464d4..edf6a51c 100644 --- a/src/modules/portfolio-margin/um-trade/getOpenOrders.ts +++ b/src/modules/portfolio-margin/um-trade/getOpenOrders.ts @@ -5,59 +5,68 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmGetOpenOrders(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmGetOpenOrders", - "Get all open USDT-M Futures orders in Portfolio Margin mode.", - { - symbol: z.string().optional().describe("Trading pair symbol to filter by"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM Open Orders\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total open orders: ${data.length}\n\n`; - data.forEach((order: any, index: number) => { - result += `**${index + 1}. ${order.symbol}**\n`; - result += ` Order ID: ${order.orderId}\n`; - result += ` Side: ${order.side} | Type: ${order.type}\n`; - result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; - result += ` Executed: ${order.executedQty}\n`; - result += ` Status: ${order.status}\n\n`; - }); - } else { - result += `No open orders found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM open orders: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginUmGetOpenOrders", + { + description: "Get all open USDT-M Futures orders in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol to filter by"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM Open Orders\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total open orders: ${data.length}\n\n`; + data.forEach((order: any, index: number) => { + result += `**${index + 1}. ${order.symbol}**\n`; + result += ` Order ID: ${order.orderId}\n`; + result += ` Side: ${order.side} | Type: ${order.type}\n`; + result += ` Price: ${order.price} | Qty: ${order.origQty}\n`; + result += ` Executed: ${order.executedQty}\n`; + result += ` Status: ${order.status}\n\n`; + }); + } else { + result += `No open orders found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM open orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/getOrder.ts b/src/modules/portfolio-margin/um-trade/getOrder.ts index 6b1eb534..81a79298 100644 --- a/src/modules/portfolio-margin/um-trade/getOrder.ts +++ b/src/modules/portfolio-margin/um-trade/getOrder.ts @@ -5,67 +5,78 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmGetOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmGetOrder", - "Query a specific USDT-M Futures order in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - orderId: z.number().int().optional().describe("Order ID to query"), - origClientOrderId: z.string().optional().describe("Original client order ID to query"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ - type: "text", - text: `❌ Either orderId or origClientOrderId must be provided` - }], - isError: true - }; - } - - const response = await portfolioMarginClient.restAPI.umOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM Order Details\n\n`; - result += `Order ID: ${data.orderId}\n`; - result += `Symbol: ${data.symbol}\n`; - result += `Side: ${data.side} | Type: ${data.type}\n`; - result += `Price: ${data.price} | Qty: ${data.origQty}\n`; - result += `Executed Qty: ${data.executedQty}\n`; - result += `Avg Price: ${data.avgPrice}\n`; - result += `Status: ${data.status}\n`; - result += `Time: ${new Date(data.time).toISOString()}`; - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM order: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginUmGetOrder", + { + description: "Query a specific USDT-M Futures order in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + orderId: z.number().int().optional().describe("Order ID to query"), + origClientOrderId: z.string().optional().describe("Original client order ID to query"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: `❌ Either orderId or origClientOrderId must be provided`, + }, + ], + isError: true, + }; } - ); + + const response = await portfolioMarginClient.restAPI.umOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM Order Details\n\n`; + result += `Order ID: ${data.orderId}\n`; + result += `Symbol: ${data.symbol}\n`; + result += `Side: ${data.side} | Type: ${data.type}\n`; + result += `Price: ${data.price} | Qty: ${data.origQty}\n`; + result += `Executed Qty: ${data.executedQty}\n`; + result += `Avg Price: ${data.avgPrice}\n`; + result += `Status: ${data.status}\n`; + result += `Time: ${new Date(data.time).toISOString()}`; + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/getUserTrades.ts b/src/modules/portfolio-margin/um-trade/getUserTrades.ts index 4f25e699..7a58e045 100644 --- a/src/modules/portfolio-margin/um-trade/getUserTrades.ts +++ b/src/modules/portfolio-margin/um-trade/getUserTrades.ts @@ -5,71 +5,86 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/getUserTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmGetUserTrades(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmGetUserTrades", - "Get USDT-M Futures trade history in Portfolio Margin mode.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().min(1).max(1000).optional().describe("Number of trades to return (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umUserTrades({ - symbol: params.symbol, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let result = `✅ Portfolio Margin UM Trade History - ${params.symbol}\n\n`; - - if (Array.isArray(data) && data.length > 0) { - result += `Total trades: ${data.length}\n\n`; - data.slice(0, 20).forEach((trade: any, index: number) => { - result += `**${index + 1}. Trade ID: ${trade.id}**\n`; - result += ` Order ID: ${trade.orderId}\n`; - result += ` Side: ${trade.side} | Price: ${trade.price}\n`; - result += ` Qty: ${trade.qty} | Quote Qty: ${trade.quoteQty}\n`; - result += ` Realized PnL: ${trade.realizedPnl}\n`; - result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; - result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; - }); - if (data.length > 20) { - result += `... and ${data.length - 20} more trades`; - } - } else { - result += `No trades found`; - } - - return { - content: [{ - type: "text", - text: result - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get Portfolio Margin UM trades: ${errorMessage}` - }], - isError: true - }; - } + server.registerTool( + "BinancePortfolioMarginUmGetUserTrades", + { + description: "Get USDT-M Futures trade history in Portfolio Margin mode.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of trades to return (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umUserTrades({ + symbol: params.symbol, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let result = `✅ Portfolio Margin UM Trade History - ${params.symbol}\n\n`; + + if (Array.isArray(data) && data.length > 0) { + result += `Total trades: ${data.length}\n\n`; + data.slice(0, 20).forEach((trade: any, index: number) => { + result += `**${index + 1}. Trade ID: ${trade.id}**\n`; + result += ` Order ID: ${trade.orderId}\n`; + result += ` Side: ${trade.side} | Price: ${trade.price}\n`; + result += ` Qty: ${trade.qty} | Quote Qty: ${trade.quoteQty}\n`; + result += ` Realized PnL: ${trade.realizedPnl}\n`; + result += ` Commission: ${trade.commission} ${trade.commissionAsset}\n`; + result += ` Time: ${new Date(trade.time).toISOString()}\n\n`; + }); + if (data.length > 20) { + result += `... and ${data.length - 20} more trades`; + } + } else { + result += `No trades found`; } - ); + + return { + content: [ + { + type: "text", + text: result, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to get Portfolio Margin UM trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/um-trade/index.ts b/src/modules/portfolio-margin/um-trade/index.ts index 75232dbe..ebbff269 100644 --- a/src/modules/portfolio-margin/um-trade/index.ts +++ b/src/modules/portfolio-margin/um-trade/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerPortfolioMarginUmNewOrder } from "./newOrder.js"; -import { registerPortfolioMarginUmCancelOrder } from "./cancelOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerPortfolioMarginUmCancelAllOrders } from "./cancelAllOrders.js"; -import { registerPortfolioMarginUmGetOrder } from "./getOrder.js"; +import { registerPortfolioMarginUmCancelOrder } from "./cancelOrder.js"; +import { registerPortfolioMarginUmChangeLeverage } from "./changeLeverage.js"; +import { registerPortfolioMarginUmChangeMarginType } from "./changeMarginType.js"; import { registerPortfolioMarginUmGetAllOrders } from "./getAllOrders.js"; import { registerPortfolioMarginUmGetOpenOrders } from "./getOpenOrders.js"; +import { registerPortfolioMarginUmGetOrder } from "./getOrder.js"; import { registerPortfolioMarginUmGetUserTrades } from "./getUserTrades.js"; -import { registerPortfolioMarginUmChangeLeverage } from "./changeLeverage.js"; -import { registerPortfolioMarginUmChangeMarginType } from "./changeMarginType.js"; +import { registerPortfolioMarginUmNewOrder } from "./newOrder.js"; export function registerPortfolioMarginUmTradeApi(server: McpServer) { - registerPortfolioMarginUmNewOrder(server); - registerPortfolioMarginUmCancelOrder(server); - registerPortfolioMarginUmCancelAllOrders(server); - registerPortfolioMarginUmGetOrder(server); - registerPortfolioMarginUmGetAllOrders(server); - registerPortfolioMarginUmGetOpenOrders(server); - registerPortfolioMarginUmGetUserTrades(server); - registerPortfolioMarginUmChangeLeverage(server); - registerPortfolioMarginUmChangeMarginType(server); + registerPortfolioMarginUmNewOrder(server); + registerPortfolioMarginUmCancelOrder(server); + registerPortfolioMarginUmCancelAllOrders(server); + registerPortfolioMarginUmGetOrder(server); + registerPortfolioMarginUmGetAllOrders(server); + registerPortfolioMarginUmGetOpenOrders(server); + registerPortfolioMarginUmGetUserTrades(server); + registerPortfolioMarginUmChangeLeverage(server); + registerPortfolioMarginUmChangeMarginType(server); } diff --git a/src/modules/portfolio-margin/um-trade/newOrder.ts b/src/modules/portfolio-margin/um-trade/newOrder.ts index cb836c33..d7fc0d75 100644 --- a/src/modules/portfolio-margin/um-trade/newOrder.ts +++ b/src/modules/portfolio-margin/um-trade/newOrder.ts @@ -5,62 +5,84 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/um-trade/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginUmNewOrder(server: McpServer) { - server.tool( - "BinancePortfolioMarginUmNewOrder", + server.registerTool( + "BinancePortfolioMarginUmNewOrder", + { + description: "Place a new USDT-M Futures order in Portfolio Margin mode. ⚠️ HIGH RISK: Futures trading involves leverage.", - { - symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"]) - .describe("Order type"), - quantity: z.string().optional().describe("Order quantity"), - price: z.string().optional().describe("Limit price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), - reduceOnly: z.boolean().optional().describe("Reduce position only"), - newClientOrderId: z.string().optional().describe("Custom client order ID"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for hedge mode"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.umNewOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin UM Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || 'MARKET'}\nStatus: ${data.status}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place Portfolio Margin UM order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., 'BTCUSDT')"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity"), + price: z.string().optional().describe("Limit price (required for LIMIT orders)"), + stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), + reduceOnly: z.boolean().optional().describe("Reduce position only"), + newClientOrderId: z.string().optional().describe("Custom client order ID"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for hedge mode"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.umNewOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin UM Order Placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || "MARKET"}\nStatus: ${data.status}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place Portfolio Margin UM order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/userdata/createListenKey.ts b/src/modules/portfolio-margin/userdata/createListenKey.ts index efbc3718..1c42a930 100644 --- a/src/modules/portfolio-margin/userdata/createListenKey.ts +++ b/src/modules/portfolio-margin/userdata/createListenKey.ts @@ -5,35 +5,43 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/userdata/createListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { portfolioMarginClient } from "../../../config/binanceClient.js"; export function registerPortfolioMarginCreateListenKey(server: McpServer) { - server.tool( - "BinancePortfolioMarginCreateListenKey", + server.registerTool( + "BinancePortfolioMarginCreateListenKey", + { + description: "Create a listen key for Portfolio Margin user data stream. The listen key is used to subscribe to account updates via WebSocket.", - {}, - async () => { - try { - const response = await portfolioMarginClient.restAPI.createListenKey(); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Listen Key Created\n\nListen Key: ${data.listenKey}\n\n**Note**: This listen key is valid for 60 minutes. Use BinancePortfolioMarginRenewListenKey to extend validity.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to create Portfolio Margin listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + }, + async () => { + try { + const response = await portfolioMarginClient.restAPI.createListenKey(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Listen Key Created\n\nListen Key: ${data.listenKey}\n\n**Note**: This listen key is valid for 60 minutes. Use BinancePortfolioMarginRenewListenKey to extend validity.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to create Portfolio Margin listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/userdata/deleteListenKey.ts b/src/modules/portfolio-margin/userdata/deleteListenKey.ts index 8fe5724d..353026cb 100644 --- a/src/modules/portfolio-margin/userdata/deleteListenKey.ts +++ b/src/modules/portfolio-margin/userdata/deleteListenKey.ts @@ -5,40 +5,50 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/userdata/deleteListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginDeleteListenKey(server: McpServer) { - server.tool( - "BinancePortfolioMarginDeleteListenKey", + server.registerTool( + "BinancePortfolioMarginDeleteListenKey", + { + description: "Close/delete a Portfolio Margin listen key. This will terminate the user data stream connection.", - { - listenKey: z.string().optional().describe("Listen key to delete") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.deleteListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }) - }); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Listen Key Deleted\n\nThe listen key has been invalidated.\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to delete Portfolio Margin listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z.string().optional().describe("Listen key to delete"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.deleteListenKey({ + ...(params.listenKey && { listenKey: params.listenKey }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Listen Key Deleted\n\nThe listen key has been invalidated.\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to delete Portfolio Margin listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/portfolio-margin/userdata/index.ts b/src/modules/portfolio-margin/userdata/index.ts index 31d3a567..d66fc97c 100644 --- a/src/modules/portfolio-margin/userdata/index.ts +++ b/src/modules/portfolio-margin/userdata/index.ts @@ -5,13 +5,14 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/userdata/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerPortfolioMarginCreateListenKey } from "./createListenKey.js"; -import { registerPortfolioMarginRenewListenKey } from "./renewListenKey.js"; import { registerPortfolioMarginDeleteListenKey } from "./deleteListenKey.js"; +import { registerPortfolioMarginRenewListenKey } from "./renewListenKey.js"; export function registerPortfolioMarginUserdataApi(server: McpServer) { - registerPortfolioMarginCreateListenKey(server); - registerPortfolioMarginRenewListenKey(server); - registerPortfolioMarginDeleteListenKey(server); + registerPortfolioMarginCreateListenKey(server); + registerPortfolioMarginRenewListenKey(server); + registerPortfolioMarginDeleteListenKey(server); } diff --git a/src/modules/portfolio-margin/userdata/renewListenKey.ts b/src/modules/portfolio-margin/userdata/renewListenKey.ts index 9aade0e2..4c051b41 100644 --- a/src/modules/portfolio-margin/userdata/renewListenKey.ts +++ b/src/modules/portfolio-margin/userdata/renewListenKey.ts @@ -5,40 +5,49 @@ * @license Apache-2.0 */ // src/modules/portfolio-margin/userdata/renewListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { portfolioMarginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { portfolioMarginClient } from "../../../config/binanceClient.js"; + export function registerPortfolioMarginRenewListenKey(server: McpServer) { - server.tool( - "BinancePortfolioMarginRenewListenKey", - "Extend the validity of a Portfolio Margin listen key by 60 minutes.", - { - listenKey: z.string().optional().describe("Listen key to renew") - }, - async (params) => { - try { - const response = await portfolioMarginClient.restAPI.renewListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }) - }); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Portfolio Margin Listen Key Renewed\n\nThe listen key validity has been extended by 60 minutes.\n\nResponse: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to renew Portfolio Margin listen key: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinancePortfolioMarginRenewListenKey", + { + description: "Extend the validity of a Portfolio Margin listen key by 60 minutes.", + inputSchema: { + listenKey: z.string().optional().describe("Listen key to renew"), + }, + }, + async (params) => { + try { + const response = await portfolioMarginClient.restAPI.renewListenKey({ + ...(params.listenKey && { listenKey: params.listenKey }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Portfolio Margin Listen Key Renewed\n\nThe listen key validity has been extended by 60 minutes.\n\nResponse: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to renew Portfolio Margin listen key: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/rebate/index.ts b/src/modules/rebate/index.ts index 5e8d5e72..5a20e726 100644 --- a/src/modules/rebate/index.ts +++ b/src/modules/rebate/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-rebate/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetSpotRebateHistoryRecords } from "./rebate-api/getSpotRebateHistoryRecords.js"; export function registerBinanceRebateTools(server: McpServer) { - registerBinanceGetSpotRebateHistoryRecords(server); + registerBinanceGetSpotRebateHistoryRecords(server); } // Alias for binance.ts compatibility diff --git a/src/modules/rebate/rebate-api/getSpotRebateHistoryRecords.ts b/src/modules/rebate/rebate-api/getSpotRebateHistoryRecords.ts index c3b46ee8..cc36b657 100644 --- a/src/modules/rebate/rebate-api/getSpotRebateHistoryRecords.ts +++ b/src/modules/rebate/rebate-api/getSpotRebateHistoryRecords.ts @@ -1,51 +1,61 @@ // src/tools/binance-pay/rebate-api/getSpotRebateHistoryRecords.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { rebateClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { rebateClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSpotRebateHistoryRecords(server: McpServer) { - server.tool( - "BinanceGetSpotRebateHistoryRecords", + server.registerTool( + "BinanceGetSpotRebateHistoryRecords", + { + description: "Retrieve the history of spot rebate records, including commission rebates and referral kickbacks, for the past 7 days or a custom date range (within 30 days).", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await rebateClient.restAPI.getSpotRebateHistoryRecords({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await rebateClient.restAPI.getSpotRebateHistoryRecords({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the history of spot rebate records, including commission rebates and referral kickbacks. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the history of spot rebate records, including commission rebates and referral kickbacks. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the history of spot rebate records: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the history of spot rebate records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account-api/getFlexibleProductPosition.ts b/src/modules/simple-earn/account-api/getFlexibleProductPosition.ts index df77fa91..86d13d83 100644 --- a/src/modules/simple-earn/account-api/getFlexibleProductPosition.ts +++ b/src/modules/simple-earn/account-api/getFlexibleProductPosition.ts @@ -1,59 +1,72 @@ // src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFlexibleProductPosition(server: McpServer) { - server.tool( - "BinanceGetFlexibleProductPosition", + server.registerTool( + "BinanceGetFlexibleProductPosition", + { + description: "Fetch your current holdings in Simple Earn Flexible Products, including total amount, reward rates, and redeem status.", - { - asset: z.string().optional().describe("Asset symbol (optional)"), - productId: z.string().optional().describe("Product ID (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying the page. Starts from 1. Default: 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleProductPosition({ - ...(params.asset && { asset: params.asset }), - ...(params.productId && { productId: params.productId }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Asset symbol (optional)"), + productId: z.string().optional().describe("Product ID (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying the page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Page size. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleProductPosition({ + ...(params.asset && { asset: params.asset }), + ...(params.productId && { productId: params.productId }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched your current holdings in Simple Earn Flexible Products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched your current holdings in Simple Earn Flexible Products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetch your current holdings in Simple Earn Flexible Products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetch your current holdings in Simple Earn Flexible Products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account-api/index.ts b/src/modules/simple-earn/account-api/index.ts index 530448c0..ce694ad7 100644 --- a/src/modules/simple-earn/account-api/index.ts +++ b/src/modules/simple-earn/account-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-simple-earn/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSimpleEarnFlexibleProductList } from "./simpleEarnFlexibleProductList.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFlexibleProductPosition } from "./getFlexibleProductPosition.js"; +import { registerBinanceSimpleEarnFlexibleProductList } from "./simpleEarnFlexibleProductList.js"; export function registerBinanceSimpleEarnAccountApiTools(server: McpServer) { - // Registers a tool to get the list of flexible earning products - registerBinanceSimpleEarnFlexibleProductList(server); + // Registers a tool to get the list of flexible earning products + registerBinanceSimpleEarnFlexibleProductList(server); - // Registers a tool to get the user's position in flexible earning products - registerBinanceGetFlexibleProductPosition(server); + // Registers a tool to get the user's position in flexible earning products + registerBinanceGetFlexibleProductPosition(server); } diff --git a/src/modules/simple-earn/account-api/simpleEarnFlexibleProductList.ts b/src/modules/simple-earn/account-api/simpleEarnFlexibleProductList.ts index 70fd0e68..eef70a29 100644 --- a/src/modules/simple-earn/account-api/simpleEarnFlexibleProductList.ts +++ b/src/modules/simple-earn/account-api/simpleEarnFlexibleProductList.ts @@ -1,57 +1,70 @@ // src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceSimpleEarnFlexibleProductList(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleProductList", + server.registerTool( + "BinanceSimpleEarnFlexibleProductList", + { + description: "Retrieve a list of available Simple Earn Flexible Products, including details like APR, purchase status, and subscription limits.", - { - asset: z.string().optional().describe("Asset symbol (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Starts from 1. Default: 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getSimpleEarnFlexibleProductList({ - ...(params.asset && { asset: params.asset }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Asset symbol (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Page size. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getSimpleEarnFlexibleProductList({ + ...(params.asset && { asset: params.asset }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve a list of available Simple Earn Flexible Products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve a list of available Simple Earn Flexible Products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of available Simple Earn Flexible Products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of available Simple Earn Flexible Products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account/getAccount.ts b/src/modules/simple-earn/account/getAccount.ts index 185a0f31..5b2634de 100644 --- a/src/modules/simple-earn/account/getAccount.ts +++ b/src/modules/simple-earn/account/getAccount.ts @@ -5,41 +5,51 @@ * @license Apache-2.0 */ // src/modules/simple-earn/account/getAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnAccount(server: McpServer) { - server.tool( - "BinanceSimpleEarnAccount", + server.registerTool( + "BinanceSimpleEarnAccount", + { + description: "Get your Simple Earn account overview. Shows total amounts in flexible and locked products, and pending rewards.", - { - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getSimpleEarnAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getSimpleEarnAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `💰 Simple Earn Account Overview\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `💰 Simple Earn Account Overview\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get account overview: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get account overview: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account/getCollateralRecord.ts b/src/modules/simple-earn/account/getCollateralRecord.ts index f788c2a7..8530432a 100644 --- a/src/modules/simple-earn/account/getCollateralRecord.ts +++ b/src/modules/simple-earn/account/getCollateralRecord.ts @@ -5,53 +5,62 @@ * @license Apache-2.0 */ // src/modules/simple-earn/account/getCollateralRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnCollateralRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnCollateralRecord", - "Get your collateral record history for flexible products used as collateral.", - { - productId: z.string().optional().describe("Filter by product ID"), - asset: z.string().optional().describe("Filter by asset"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleCollateralRecord({ - ...(params.productId && { productId: params.productId }), - ...(params.asset && { asset: params.asset }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceSimpleEarnCollateralRecord", + { + description: "Get your collateral record history for flexible products used as collateral.", + inputSchema: { + productId: z.string().optional().describe("Filter by product ID"), + asset: z.string().optional().describe("Filter by asset"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getCollateralRecord({ + ...(params.productId && { productId: params.productId }), + ...(params.asset && { asset: params.asset }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Collateral Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Collateral Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get collateral records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get collateral records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account/getRewardRecord.ts b/src/modules/simple-earn/account/getRewardRecord.ts index 9d6fe94e..f96ae5b2 100644 --- a/src/modules/simple-earn/account/getRewardRecord.ts +++ b/src/modules/simple-earn/account/getRewardRecord.ts @@ -5,55 +5,65 @@ * @license Apache-2.0 */ // src/modules/simple-earn/account/getRewardRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnRewardRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnRewardRecord", + server.registerTool( + "BinanceSimpleEarnRewardRecord", + { + description: "Get your reward distribution history. Shows all rewards earned from Simple Earn products.", - { - productId: z.string().optional().describe("Filter by product ID"), - asset: z.string().optional().describe("Filter by asset"), - type: z.enum(["BONUS", "REALTIME", "REWARDS"]).optional().describe("Filter by reward type"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleRewardsRecord({ - ...(params.productId && { productId: params.productId }), - ...(params.asset && { asset: params.asset }), - ...(params.type && { type: params.type }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().optional().describe("Filter by product ID"), + asset: z.string().optional().describe("Filter by asset"), + type: z.enum(["BONUS", "REALTIME", "REWARDS"]).optional().describe("Filter by reward type"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleRewardsHistory({ + ...(params.productId && { productId: params.productId }), + ...(params.asset && { asset: params.asset }), + ...(params.type && { type: params.type }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `🎁 Reward Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `🎁 Reward Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get reward records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get reward records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/account/index.ts b/src/modules/simple-earn/account/index.ts index 34dcf263..cff375cf 100644 --- a/src/modules/simple-earn/account/index.ts +++ b/src/modules/simple-earn/account/index.ts @@ -5,13 +5,14 @@ * @license Apache-2.0 */ // src/modules/simple-earn/account/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerSimpleEarnAccount } from "./getAccount.js"; import { registerSimpleEarnCollateralRecord } from "./getCollateralRecord.js"; import { registerSimpleEarnRewardRecord } from "./getRewardRecord.js"; export function registerSimpleEarnAccountTools(server: McpServer) { - registerSimpleEarnAccount(server); - registerSimpleEarnCollateralRecord(server); - registerSimpleEarnRewardRecord(server); + registerSimpleEarnAccount(server); + registerSimpleEarnCollateralRecord(server); + registerSimpleEarnRewardRecord(server); } diff --git a/src/modules/simple-earn/earn-api/index.ts b/src/modules/simple-earn/earn-api/index.ts index 7d2a23e0..3c1f18b4 100644 --- a/src/modules/simple-earn/earn-api/index.ts +++ b/src/modules/simple-earn/earn-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-simple-earn/earn-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubscribeFlexibleProduct } from "./subscribeFlexibleProduct.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceRedeemFlexibleProduct } from "./redeemFlexibleProduct.js"; +import { registerBinanceSubscribeFlexibleProduct } from "./subscribeFlexibleProduct.js"; export function registerBinanceSimpleEarnApiTools(server: McpServer) { - // Register the route for subscribing to a flexible earn product - registerBinanceSubscribeFlexibleProduct(server); + // Register the route for subscribing to a flexible earn product + registerBinanceSubscribeFlexibleProduct(server); - // Register the route for redeeming from a flexible earn product - registerBinanceRedeemFlexibleProduct(server); + // Register the route for redeeming from a flexible earn product + registerBinanceRedeemFlexibleProduct(server); } diff --git a/src/modules/simple-earn/earn-api/redeemFlexibleProduct.ts b/src/modules/simple-earn/earn-api/redeemFlexibleProduct.ts index 13f0fd16..ba5f2754 100644 --- a/src/modules/simple-earn/earn-api/redeemFlexibleProduct.ts +++ b/src/modules/simple-earn/earn-api/redeemFlexibleProduct.ts @@ -1,71 +1,81 @@ // src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemFlexibleProduct(server: McpServer) { - server.tool( - "BinanceRedeemFlexibleProduct", + server.registerTool( + "BinanceRedeemFlexibleProduct", + { + description: "Allows users to redeem their funds from a Flexible Earn investment product using a programmatic HTTP POST request.", - { - productId: z.string().describe("Product ID"), - redeemAll: z.boolean().optional().describe("true or false, default to false"), - amount: z.number().positive().optional().describe("If redeemAll is false, amount is mandatory"), - destAccount: z - .enum(["SPOT", "FUND"]) - .optional() - .describe("Destination account: SPOT or FUND; default is SPOT"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const { productId, redeemAll = false, amount, destAccount, recvWindow } = params; + inputSchema: { + productId: z.string().describe("Product ID"), + redeemAll: z.boolean().optional().describe("true or false, default to false"), + amount: z + .number() + .positive() + .optional() + .describe("If redeemAll is false, amount is mandatory"), + destAccount: z + .enum(["SPOT", "FUND"]) + .optional() + .describe("Destination account: SPOT or FUND; default is SPOT"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const { productId, redeemAll = false, amount, destAccount, recvWindow } = params; - // Defensive check - if (!redeemAll && (amount === undefined || amount <= 0)) { - return { - content: [ - { - type: "text", - text: "You must provide a valid amount when redeemAll is false." - } - ], - isError: true - }; - } + // Defensive check + if (!redeemAll && (amount === undefined || amount <= 0)) { + return { + content: [ + { + type: "text", + text: "You must provide a valid amount when redeemAll is false.", + }, + ], + isError: true, + }; + } - const response = await simpleEarnClient.restAPI.redeemFlexibleProduct({ - productId, - ...(redeemAll !== undefined && { redeemAll }), - ...(amount !== undefined && { amount }), - ...(destAccount && { destAccount }), - ...(recvWindow && { recvWindow }) - }); + const response = await (simpleEarnClient as any).restAPI.redeemFlexibleProduct({ + productId, + ...(redeemAll !== undefined && { redeemAll }), + ...(amount !== undefined && { amount }), + ...(destAccount && { destAccount }), + ...(recvWindow && { recvWindow }), + }); - const data = await response.data(); + const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Successfully redeem funds from a flexible earn investment. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to allows users to redeem their funds from a Flexible Earn investment: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Successfully redeem funds from a flexible earn investment. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to allows users to redeem their funds from a Flexible Earn investment: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/earn-api/subscribeFlexibleProduct.ts b/src/modules/simple-earn/earn-api/subscribeFlexibleProduct.ts index 5ec0a898..eb961569 100644 --- a/src/modules/simple-earn/earn-api/subscribeFlexibleProduct.ts +++ b/src/modules/simple-earn/earn-api/subscribeFlexibleProduct.ts @@ -1,56 +1,62 @@ // src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeFlexibleProduct(server: McpServer) { - server.tool( - "BinanceSubscribeFlexibleProduct", + server.registerTool( + "BinanceSubscribeFlexibleProduct", + { + description: "Subscribe to a Simple Earn Flexible Product by specifying the product ID and amount. Optional parameters include auto-subscribe and source account. ", - { - productId: z.string().describe("Product ID"), - amount: z.number().positive().describe("Amount to purchase"), - autoSubscribe: z.boolean().optional().describe("true or false, default is true"), - sourceAccount: z - .enum(["SPOT", "FUND", "ALL"]) - .optional() - .describe("Source account: SPOT, FUND, or ALL; default is SPOT"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.subscribeFlexibleProduct({ - productId: params.productId, - amount: params.amount, - ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), - ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID"), + amount: z.number().positive().describe("Amount to purchase"), + autoSubscribe: z.boolean().optional().describe("true or false, default is true"), + sourceAccount: z + .enum(["SPOT", "FUND", "ALL"]) + .optional() + .describe("Source account: SPOT, FUND, or ALL; default is SPOT"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.subscribeFlexibleProduct({ + productId: params.productId, + amount: params.amount, + ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), + ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Subscribed to Simple Earn Flexible Product id ${ + params.productId + } and amount${params.amount}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Subscribed to Simple Earn Flexible Product id ${ - params.productId - } and amount${params.amount}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to subscribe to a Simple Earn Flexible Product: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to subscribe to a Simple Earn Flexible Product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getFlexiblePosition.ts b/src/modules/simple-earn/flexible/getFlexiblePosition.ts index ca087462..c658d35b 100644 --- a/src/modules/simple-earn/flexible/getFlexiblePosition.ts +++ b/src/modules/simple-earn/flexible/getFlexiblePosition.ts @@ -5,49 +5,59 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getFlexiblePosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexiblePosition(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexiblePosition", + server.registerTool( + "BinanceSimpleEarnFlexiblePosition", + { + description: "Get your current Simple Earn Flexible positions. Shows subscribed amount, cumulative rewards, and APR for each product.", - { - asset: z.string().optional().describe("Filter by asset symbol"), - productId: z.string().optional().describe("Filter by product ID"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleProductPosition({ - ...(params.asset && { asset: params.asset }), - ...(params.productId && { productId: params.productId }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by asset symbol"), + productId: z.string().optional().describe("Filter by product ID"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleProductPosition({ + ...(params.asset && { asset: params.asset }), + ...(params.productId && { productId: params.productId }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Your Flexible Earn Positions\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Your Flexible Earn Positions\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get flexible positions: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get flexible positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getFlexibleProductList.ts b/src/modules/simple-earn/flexible/getFlexibleProductList.ts index 61bdfab3..1f6199c5 100644 --- a/src/modules/simple-earn/flexible/getFlexibleProductList.ts +++ b/src/modules/simple-earn/flexible/getFlexibleProductList.ts @@ -5,47 +5,63 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getFlexibleProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexibleProductList(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleProductList", + server.registerTool( + "BinanceSimpleEarnFlexibleProductList", + { + description: "Get available Simple Earn Flexible products. Returns product details including APR, minimum purchase amount, and availability status.", - { - asset: z.string().optional().describe("Filter by asset symbol (e.g., 'BTC', 'ETH')"), - current: z.number().int().min(1).default(1).optional().describe("Page number, starting from 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size (1-100)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getSimpleEarnFlexibleProductList({ - ...(params.asset && { asset: params.asset }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by asset symbol (e.g., 'BTC', 'ETH')"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Page number, starting from 1"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size (1-100)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getSimpleEarnFlexibleProductList({ + ...(params.asset && { asset: params.asset }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📋 Simple Earn Flexible Products\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 Simple Earn Flexible Products\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get flexible product list: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get flexible product list: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getFlexibleSubscriptionPreview.ts b/src/modules/simple-earn/flexible/getFlexibleSubscriptionPreview.ts index 16fe7231..96746406 100644 --- a/src/modules/simple-earn/flexible/getFlexibleSubscriptionPreview.ts +++ b/src/modules/simple-earn/flexible/getFlexibleSubscriptionPreview.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getFlexibleSubscriptionPreview.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexibleSubscriptionPreview(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleSubscriptionPreview", + server.registerTool( + "BinanceSimpleEarnFlexibleSubscriptionPreview", + { + description: "Preview a flexible product subscription before committing. Shows expected rewards and next interest date.", - { - productId: z.string().describe("Product ID to preview"), - amount: z.number().positive().describe("Amount to preview subscription for"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleSubscriptionPreview({ - productId: params.productId, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID to preview"), + amount: z.number().positive().describe("Amount to preview subscription for"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleSubscriptionPreview({ + productId: params.productId, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `🔮 Subscription Preview\n\nProduct ID: ${params.productId}\nAmount: ${params.amount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `🔮 Subscription Preview\n\nProduct ID: ${params.productId}\nAmount: ${params.amount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to preview subscription: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to preview subscription: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getRateHistory.ts b/src/modules/simple-earn/flexible/getRateHistory.ts index 8f4e71de..9c6f7b14 100644 --- a/src/modules/simple-earn/flexible/getRateHistory.ts +++ b/src/modules/simple-earn/flexible/getRateHistory.ts @@ -5,51 +5,61 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexibleRateHistory(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleRateHistory", + server.registerTool( + "BinanceSimpleEarnFlexibleRateHistory", + { + description: "Get historical APR rates for a flexible product. Useful for analyzing rate trends and making informed investment decisions.", - { - productId: z.string().describe("Product ID to get rate history for"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleRateHistory({ - productId: params.productId, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID to get rate history for"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleRewardsHistory({ + productId: params.productId, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📈 Flexible Product Rate History\n\nProduct ID: ${params.productId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📈 Flexible Product Rate History\n\nProduct ID: ${params.productId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get rate history: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get rate history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getRedemptionRecord.ts b/src/modules/simple-earn/flexible/getRedemptionRecord.ts index 9a672005..ba28b63d 100644 --- a/src/modules/simple-earn/flexible/getRedemptionRecord.ts +++ b/src/modules/simple-earn/flexible/getRedemptionRecord.ts @@ -5,55 +5,65 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getRedemptionRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexibleRedemptionRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleRedemptionRecord", + server.registerTool( + "BinanceSimpleEarnFlexibleRedemptionRecord", + { + description: "Get your flexible product redemption history. Shows all past redemptions with amounts, dates, and status.", - { - productId: z.string().optional().describe("Filter by product ID"), - redeemId: z.string().optional().describe("Filter by redemption ID"), - asset: z.string().optional().describe("Filter by asset"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleRedemptionRecord({ - ...(params.productId && { productId: params.productId }), - ...(params.redeemId && { redeemId: params.redeemId }), - ...(params.asset && { asset: params.asset }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().optional().describe("Filter by product ID"), + redeemId: z.string().optional().describe("Filter by redemption ID"), + asset: z.string().optional().describe("Filter by asset"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleRedemptionRecord({ + ...(params.productId && { productId: params.productId }), + ...(params.redeemId && { redeemId: params.redeemId }), + ...(params.asset && { asset: params.asset }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Flexible Redemption Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Flexible Redemption Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get redemption records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get redemption records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/getSubscriptionRecord.ts b/src/modules/simple-earn/flexible/getSubscriptionRecord.ts index aa368a72..e5266f69 100644 --- a/src/modules/simple-earn/flexible/getSubscriptionRecord.ts +++ b/src/modules/simple-earn/flexible/getSubscriptionRecord.ts @@ -5,55 +5,65 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/getSubscriptionRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnFlexibleSubscriptionRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleSubscriptionRecord", + server.registerTool( + "BinanceSimpleEarnFlexibleSubscriptionRecord", + { + description: "Get your flexible product subscription history. Shows all past subscriptions with amounts, dates, and status.", - { - productId: z.string().optional().describe("Filter by product ID"), - purchaseId: z.string().optional().describe("Filter by purchase ID"), - asset: z.string().optional().describe("Filter by asset"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleSubscriptionRecord({ - ...(params.productId && { productId: params.productId }), - ...(params.purchaseId && { purchaseId: params.purchaseId }), - ...(params.asset && { asset: params.asset }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().optional().describe("Filter by product ID"), + purchaseId: z.string().optional().describe("Filter by purchase ID"), + asset: z.string().optional().describe("Filter by asset"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleSubscriptionRecord({ + ...(params.productId && { productId: params.productId }), + ...(params.purchaseId && { purchaseId: params.purchaseId }), + ...(params.asset && { asset: params.asset }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Flexible Subscription Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Flexible Subscription Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get subscription records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get subscription records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/index.ts b/src/modules/simple-earn/flexible/index.ts index f34ea944..26818904 100644 --- a/src/modules/simple-earn/flexible/index.ts +++ b/src/modules/simple-earn/flexible/index.ts @@ -5,23 +5,24 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerSimpleEarnFlexibleProductList } from "./getFlexibleProductList.js"; -import { registerSimpleEarnSubscribeFlexible } from "./subscribeFlexible.js"; -import { registerSimpleEarnRedeemFlexible } from "./redeemFlexible.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerSimpleEarnFlexiblePosition } from "./getFlexiblePosition.js"; +import { registerSimpleEarnFlexibleProductList } from "./getFlexibleProductList.js"; import { registerSimpleEarnFlexibleSubscriptionPreview } from "./getFlexibleSubscriptionPreview.js"; import { registerSimpleEarnFlexibleRateHistory } from "./getRateHistory.js"; -import { registerSimpleEarnFlexibleSubscriptionRecord } from "./getSubscriptionRecord.js"; import { registerSimpleEarnFlexibleRedemptionRecord } from "./getRedemptionRecord.js"; +import { registerSimpleEarnFlexibleSubscriptionRecord } from "./getSubscriptionRecord.js"; +import { registerSimpleEarnRedeemFlexible } from "./redeemFlexible.js"; +import { registerSimpleEarnSubscribeFlexible } from "./subscribeFlexible.js"; export function registerSimpleEarnFlexibleTools(server: McpServer) { - registerSimpleEarnFlexibleProductList(server); - registerSimpleEarnSubscribeFlexible(server); - registerSimpleEarnRedeemFlexible(server); - registerSimpleEarnFlexiblePosition(server); - registerSimpleEarnFlexibleSubscriptionPreview(server); - registerSimpleEarnFlexibleRateHistory(server); - registerSimpleEarnFlexibleSubscriptionRecord(server); - registerSimpleEarnFlexibleRedemptionRecord(server); + registerSimpleEarnFlexibleProductList(server); + registerSimpleEarnSubscribeFlexible(server); + registerSimpleEarnRedeemFlexible(server); + registerSimpleEarnFlexiblePosition(server); + registerSimpleEarnFlexibleSubscriptionPreview(server); + registerSimpleEarnFlexibleRateHistory(server); + registerSimpleEarnFlexibleSubscriptionRecord(server); + registerSimpleEarnFlexibleRedemptionRecord(server); } diff --git a/src/modules/simple-earn/flexible/redeemFlexible.ts b/src/modules/simple-earn/flexible/redeemFlexible.ts index 9664b62d..feaef3c6 100644 --- a/src/modules/simple-earn/flexible/redeemFlexible.ts +++ b/src/modules/simple-earn/flexible/redeemFlexible.ts @@ -5,49 +5,66 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/redeemFlexible.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnRedeemFlexible(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleRedeem", + server.registerTool( + "BinanceSimpleEarnFlexibleRedeem", + { + description: "Redeem from a Simple Earn Flexible product. Funds are returned to your spot wallet. 💸 Instant redemption available!", - { - productId: z.string().describe("Product ID to redeem from"), - redeemAll: z.boolean().optional().describe("Redeem all position (true/false)"), - amount: z.number().positive().optional().describe("Amount to redeem (required if redeemAll is false)"), - destAccount: z.enum(["SPOT", "FUND"]).optional().describe("Destination account (default: SPOT)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.redeemFlexibleProduct({ - productId: params.productId, - ...(params.redeemAll !== undefined && { redeemAll: params.redeemAll }), - ...(params.amount && { amount: params.amount }), - ...(params.destAccount && { destAccount: params.destAccount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID to redeem from"), + redeemAll: z.boolean().optional().describe("Redeem all position (true/false)"), + amount: z + .number() + .positive() + .optional() + .describe("Amount to redeem (required if redeemAll is false)"), + destAccount: z + .enum(["SPOT", "FUND"]) + .optional() + .describe("Destination account (default: SPOT)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.redeemFlexibleProduct({ + productId: params.productId, + ...(params.redeemAll !== undefined && { redeemAll: params.redeemAll }), + ...(params.amount && { amount: params.amount }), + ...(params.destAccount && { destAccount: params.destAccount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Flexible Product Redemption Successful!\n\nProduct ID: ${params.productId}\nAmount: ${params.redeemAll ? "All" : params.amount}\nRedemption ID: ${data.redeemId || "N/A"}\n\n💡 Funds will be credited to your ${params.destAccount || "SPOT"} account shortly.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Flexible Product Redemption Successful!\n\nProduct ID: ${params.productId}\nAmount: ${params.redeemAll ? 'All' : params.amount}\nRedemption ID: ${data.redeemId || 'N/A'}\n\n💡 Funds will be credited to your ${params.destAccount || 'SPOT'} account shortly.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to redeem flexible product: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to redeem flexible product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/flexible/subscribeFlexible.ts b/src/modules/simple-earn/flexible/subscribeFlexible.ts index a06ea01d..91c38bd3 100644 --- a/src/modules/simple-earn/flexible/subscribeFlexible.ts +++ b/src/modules/simple-earn/flexible/subscribeFlexible.ts @@ -5,50 +5,65 @@ * @license Apache-2.0 */ // src/modules/simple-earn/flexible/subscribeFlexible.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnSubscribeFlexible(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleSubscribe", + server.registerTool( + "BinanceSimpleEarnFlexibleSubscribe", + { + description: "Subscribe to a Simple Earn Flexible product to earn daily rewards. Funds can be redeemed anytime. 💰 Start earning passive income on your crypto!", - { - productId: z.string().describe("Product ID from flexible product list"), - amount: z.number().positive().describe("Amount to subscribe"), - autoSubscribe: z.boolean().optional().describe("Auto-subscribe on redemption (default: true)"), - sourceAccount: z.enum(["SPOT", "FUND", "ALL"]).optional() - .describe("Source account for funds (default: SPOT)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.subscribeFlexibleProduct({ - productId: params.productId, - amount: params.amount, - ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), - ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID from flexible product list"), + amount: z.number().positive().describe("Amount to subscribe"), + autoSubscribe: z + .boolean() + .optional() + .describe("Auto-subscribe on redemption (default: true)"), + sourceAccount: z + .enum(["SPOT", "FUND", "ALL"]) + .optional() + .describe("Source account for funds (default: SPOT)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.subscribeFlexibleProduct({ + productId: params.productId, + amount: params.amount, + ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), + ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Flexible Product Subscription Successful!\n\nProduct ID: ${params.productId}\nAmount: ${params.amount}\nPurchase ID: ${data.purchaseId || "N/A"}\n\n💡 Your funds will start earning rewards within 24 hours.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Flexible Product Subscription Successful!\n\nProduct ID: ${params.productId}\nAmount: ${params.amount}\nPurchase ID: ${data.purchaseId || 'N/A'}\n\n💡 Your funds will start earning rewards within 24 hours.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to subscribe to flexible product: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to subscribe to flexible product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/index.ts b/src/modules/simple-earn/index.ts index 6d0e39fa..ce4705ac 100644 --- a/src/modules/simple-earn/index.ts +++ b/src/modules/simple-earn/index.ts @@ -1,14 +1,15 @@ // src/tools/binance-simple-earn/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSimpleEarnApiTools } from "./earn-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSimpleEarnAccountApiTools } from "./account-api/index.js"; +import { registerBinanceSimpleEarnApiTools } from "./earn-api/index.js"; export function registerBinanceSimpleEarnTools(server: McpServer) { - // Registers core API tools like subscribing to flexible products - registerBinanceSimpleEarnApiTools(server); + // Registers core API tools like subscribing to flexible products + registerBinanceSimpleEarnApiTools(server); - // Registers account-related tools like viewing product lists and positions - registerBinanceSimpleEarnAccountApiTools(server); + // Registers account-related tools like viewing product lists and positions + registerBinanceSimpleEarnAccountApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/simple-earn/locked/getLockedPersonalQuota.ts b/src/modules/simple-earn/locked/getLockedPersonalQuota.ts index d7030053..2e9479a0 100644 --- a/src/modules/simple-earn/locked/getLockedPersonalQuota.ts +++ b/src/modules/simple-earn/locked/getLockedPersonalQuota.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getLockedPersonalQuota.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedPersonalQuota(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedPersonalQuota", + server.registerTool( + "BinanceSimpleEarnLockedPersonalQuota", + { + description: "Get your personal subscription quota for a locked product. Shows remaining quota available to subscribe.", - { - projectId: z.string().describe("Project ID to check quota for"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getLockedPersonalLeftQuota({ - projectId: params.projectId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + projectId: z.string().describe("Project ID to check quota for"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getLockedPersonalLeftQuota({ + projectId: params.projectId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Personal Quota for Project ${params.projectId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Personal Quota for Project ${params.projectId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get personal quota: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get personal quota: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/getLockedPosition.ts b/src/modules/simple-earn/locked/getLockedPosition.ts index 34be903e..2cf19049 100644 --- a/src/modules/simple-earn/locked/getLockedPosition.ts +++ b/src/modules/simple-earn/locked/getLockedPosition.ts @@ -5,51 +5,61 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getLockedPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedPosition(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedPosition", + server.registerTool( + "BinanceSimpleEarnLockedPosition", + { + description: "Get your current Simple Earn Locked positions. Shows locked amount, rewards, maturity date, and APR.", - { - asset: z.string().optional().describe("Filter by asset symbol"), - positionId: z.string().optional().describe("Filter by position ID"), - projectId: z.string().optional().describe("Filter by project ID"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getLockedProductPosition({ - ...(params.asset && { asset: params.asset }), - ...(params.positionId && { positionId: params.positionId }), - ...(params.projectId && { projectId: params.projectId }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by asset symbol"), + positionId: z.string().optional().describe("Filter by position ID"), + projectId: z.string().optional().describe("Filter by project ID"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getLockedProductPosition({ + ...(params.asset && { asset: params.asset }), + ...(params.positionId && { positionId: params.positionId }), + ...(params.projectId && { projectId: params.projectId }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📊 Your Locked Earn Positions\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📊 Your Locked Earn Positions\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get locked positions: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get locked positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/getLockedProductList.ts b/src/modules/simple-earn/locked/getLockedProductList.ts index da7189c8..d29983ed 100644 --- a/src/modules/simple-earn/locked/getLockedProductList.ts +++ b/src/modules/simple-earn/locked/getLockedProductList.ts @@ -5,47 +5,63 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getLockedProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedProductList(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedProductList", + server.registerTool( + "BinanceSimpleEarnLockedProductList", + { + description: "Get available Simple Earn Locked products. Locked products offer higher APR in exchange for locking funds for a fixed duration.", - { - asset: z.string().optional().describe("Filter by asset symbol (e.g., 'BTC', 'ETH')"), - current: z.number().int().min(1).default(1).optional().describe("Page number, starting from 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size (1-100)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getSimpleEarnLockedProductList({ - ...(params.asset && { asset: params.asset }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by asset symbol (e.g., 'BTC', 'ETH')"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Page number, starting from 1"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size (1-100)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getSimpleEarnLockedProductList({ + ...(params.asset && { asset: params.asset }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📋 Simple Earn Locked Products\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 Simple Earn Locked Products\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get locked product list: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get locked product list: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/getLockedSubscriptionPreview.ts b/src/modules/simple-earn/locked/getLockedSubscriptionPreview.ts index f4dab642..bc55f8c0 100644 --- a/src/modules/simple-earn/locked/getLockedSubscriptionPreview.ts +++ b/src/modules/simple-earn/locked/getLockedSubscriptionPreview.ts @@ -5,47 +5,57 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getLockedSubscriptionPreview.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedSubscriptionPreview(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedSubscriptionPreview", + server.registerTool( + "BinanceSimpleEarnLockedSubscriptionPreview", + { + description: "Preview a locked product subscription before committing. Shows expected rewards, lock duration, and maturity date.", - { - projectId: z.string().describe("Project ID to preview"), - amount: z.number().positive().describe("Amount to preview subscription for"), - autoSubscribe: z.boolean().optional().describe("Include auto-subscribe in preview"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getLockedSubscriptionPreview({ - projectId: params.projectId, - amount: params.amount, - ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + projectId: z.string().describe("Project ID to preview"), + amount: z.number().positive().describe("Amount to preview subscription for"), + autoSubscribe: z.boolean().optional().describe("Include auto-subscribe in preview"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getLockedSubscriptionPreview({ + projectId: params.projectId, + amount: params.amount, + ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `🔮 Locked Subscription Preview\n\nProject ID: ${params.projectId}\nAmount: ${params.amount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `🔮 Locked Subscription Preview\n\nProject ID: ${params.projectId}\nAmount: ${params.amount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to preview subscription: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to preview subscription: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/getRedemptionRecord.ts b/src/modules/simple-earn/locked/getRedemptionRecord.ts index ad82fb74..fe4e4b63 100644 --- a/src/modules/simple-earn/locked/getRedemptionRecord.ts +++ b/src/modules/simple-earn/locked/getRedemptionRecord.ts @@ -5,55 +5,65 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getRedemptionRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedRedemptionRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedRedemptionRecord", + server.registerTool( + "BinanceSimpleEarnLockedRedemptionRecord", + { + description: "Get your locked product redemption history. Shows all redemptions including early redemptions and matured positions.", - { - positionId: z.string().optional().describe("Filter by position ID"), - redeemId: z.string().optional().describe("Filter by redemption ID"), - asset: z.string().optional().describe("Filter by asset"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getLockedRedemptionRecord({ - ...(params.positionId && { positionId: params.positionId }), - ...(params.redeemId && { redeemId: params.redeemId }), - ...(params.asset && { asset: params.asset }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + positionId: z.string().optional().describe("Filter by position ID"), + redeemId: z.string().optional().describe("Filter by redemption ID"), + asset: z.string().optional().describe("Filter by asset"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getLockedRedemptionRecord({ + ...(params.positionId && { positionId: params.positionId }), + ...(params.redeemId && { redeemId: params.redeemId }), + ...(params.asset && { asset: params.asset }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Locked Redemption Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Locked Redemption Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get redemption records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get redemption records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/getSubscriptionRecord.ts b/src/modules/simple-earn/locked/getSubscriptionRecord.ts index 5a9f4a65..85faf2fa 100644 --- a/src/modules/simple-earn/locked/getSubscriptionRecord.ts +++ b/src/modules/simple-earn/locked/getSubscriptionRecord.ts @@ -5,53 +5,63 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/getSubscriptionRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnLockedSubscriptionRecord(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedSubscriptionRecord", + server.registerTool( + "BinanceSimpleEarnLockedSubscriptionRecord", + { + description: "Get your locked product subscription history. Shows all past subscriptions with amounts, dates, and status.", - { - purchaseId: z.string().optional().describe("Filter by purchase ID"), - asset: z.string().optional().describe("Filter by asset"), - startTime: z.number().int().optional().describe("Start time in ms"), - endTime: z.number().int().optional().describe("End time in ms"), - current: z.number().int().min(1).default(1).optional().describe("Page number"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getLockedSubscriptionRecord({ - ...(params.purchaseId && { purchaseId: params.purchaseId }), - ...(params.asset && { asset: params.asset }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + purchaseId: z.string().optional().describe("Filter by purchase ID"), + asset: z.string().optional().describe("Filter by asset"), + startTime: z.number().int().optional().describe("Start time in ms"), + endTime: z.number().int().optional().describe("End time in ms"), + current: z.number().int().min(1).default(1).optional().describe("Page number"), + size: z.number().int().min(1).max(100).default(10).optional().describe("Page size"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getLockedSubscriptionRecord({ + ...(params.purchaseId && { purchaseId: params.purchaseId }), + ...(params.asset && { asset: params.asset }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `📜 Locked Subscription Records\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📜 Locked Subscription Records\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to get subscription records: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to get subscription records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/index.ts b/src/modules/simple-earn/locked/index.ts index aa52a9c2..a404ca4d 100644 --- a/src/modules/simple-earn/locked/index.ts +++ b/src/modules/simple-earn/locked/index.ts @@ -5,25 +5,26 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerSimpleEarnLockedProductList } from "./getLockedProductList.js"; -import { registerSimpleEarnSubscribeLocked } from "./subscribeLocked.js"; -import { registerSimpleEarnRedeemLocked } from "./redeemLocked.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerSimpleEarnLockedPersonalQuota } from "./getLockedPersonalQuota.js"; import { registerSimpleEarnLockedPosition } from "./getLockedPosition.js"; +import { registerSimpleEarnLockedProductList } from "./getLockedProductList.js"; import { registerSimpleEarnLockedSubscriptionPreview } from "./getLockedSubscriptionPreview.js"; -import { registerSimpleEarnSetAutoSubscribe } from "./setAutoSubscribe.js"; -import { registerSimpleEarnLockedPersonalQuota } from "./getLockedPersonalQuota.js"; -import { registerSimpleEarnLockedSubscriptionRecord } from "./getSubscriptionRecord.js"; import { registerSimpleEarnLockedRedemptionRecord } from "./getRedemptionRecord.js"; +import { registerSimpleEarnLockedSubscriptionRecord } from "./getSubscriptionRecord.js"; +import { registerSimpleEarnRedeemLocked } from "./redeemLocked.js"; +import { registerSimpleEarnSetAutoSubscribe } from "./setAutoSubscribe.js"; +import { registerSimpleEarnSubscribeLocked } from "./subscribeLocked.js"; export function registerSimpleEarnLockedTools(server: McpServer) { - registerSimpleEarnLockedProductList(server); - registerSimpleEarnSubscribeLocked(server); - registerSimpleEarnRedeemLocked(server); - registerSimpleEarnLockedPosition(server); - registerSimpleEarnLockedSubscriptionPreview(server); - registerSimpleEarnSetAutoSubscribe(server); - registerSimpleEarnLockedPersonalQuota(server); - registerSimpleEarnLockedSubscriptionRecord(server); - registerSimpleEarnLockedRedemptionRecord(server); + registerSimpleEarnLockedProductList(server); + registerSimpleEarnSubscribeLocked(server); + registerSimpleEarnRedeemLocked(server); + registerSimpleEarnLockedPosition(server); + registerSimpleEarnLockedSubscriptionPreview(server); + registerSimpleEarnSetAutoSubscribe(server); + registerSimpleEarnLockedPersonalQuota(server); + registerSimpleEarnLockedSubscriptionRecord(server); + registerSimpleEarnLockedRedemptionRecord(server); } diff --git a/src/modules/simple-earn/locked/redeemLocked.ts b/src/modules/simple-earn/locked/redeemLocked.ts index ab790156..1e434770 100644 --- a/src/modules/simple-earn/locked/redeemLocked.ts +++ b/src/modules/simple-earn/locked/redeemLocked.ts @@ -5,43 +5,53 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/redeemLocked.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnRedeemLocked(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedRedeem", + server.registerTool( + "BinanceSimpleEarnLockedRedeem", + { + description: "Redeem from a Simple Earn Locked product. ⚠️ Early redemption may forfeit rewards. Check product terms first.", - { - positionId: z.string().describe("Position ID to redeem"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.redeemLockedProduct({ - positionId: params.positionId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + positionId: z.string().describe("Position ID to redeem"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.redeemLockedProduct({ + positionId: params.positionId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Locked Product Redemption Initiated!\n\nPosition ID: ${params.positionId}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Locked Product Redemption Initiated!\n\nPosition ID: ${params.positionId}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to redeem locked product: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to redeem locked product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/setAutoSubscribe.ts b/src/modules/simple-earn/locked/setAutoSubscribe.ts index 88daaa0a..10fc3f68 100644 --- a/src/modules/simple-earn/locked/setAutoSubscribe.ts +++ b/src/modules/simple-earn/locked/setAutoSubscribe.ts @@ -5,45 +5,55 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/setAutoSubscribe.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnSetAutoSubscribe(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedSetAutoSubscribe", + server.registerTool( + "BinanceSimpleEarnLockedSetAutoSubscribe", + { + description: "Enable or disable auto-subscribe for a locked position. When enabled, funds automatically re-subscribe when the lock period ends.", - { - positionId: z.string().describe("Position ID to update"), - autoSubscribe: z.boolean().describe("Enable (true) or disable (false) auto-subscribe"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.setLockedAutoSubscribe({ - positionId: params.positionId, - autoSubscribe: params.autoSubscribe, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + positionId: z.string().describe("Position ID to update"), + autoSubscribe: z.boolean().describe("Enable (true) or disable (false) auto-subscribe"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.setLockedAutoSubscribe({ + positionId: params.positionId, + autoSubscribe: params.autoSubscribe, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Auto-Subscribe Updated!\n\nPosition ID: ${params.positionId}\nAuto-Subscribe: ${params.autoSubscribe ? "Enabled" : "Disabled"}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Auto-Subscribe Updated!\n\nPosition ID: ${params.positionId}\nAuto-Subscribe: ${params.autoSubscribe ? 'Enabled' : 'Disabled'}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to update auto-subscribe: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to update auto-subscribe: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/simple-earn/locked/subscribeLocked.ts b/src/modules/simple-earn/locked/subscribeLocked.ts index e288bdc3..2da5c588 100644 --- a/src/modules/simple-earn/locked/subscribeLocked.ts +++ b/src/modules/simple-earn/locked/subscribeLocked.ts @@ -5,50 +5,62 @@ * @license Apache-2.0 */ // src/modules/simple-earn/locked/subscribeLocked.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerSimpleEarnSubscribeLocked(server: McpServer) { - server.tool( - "BinanceSimpleEarnLockedSubscribe", + server.registerTool( + "BinanceSimpleEarnLockedSubscribe", + { + description: "Subscribe to a Simple Earn Locked product. ⚠️ Funds will be locked for the specified duration. Higher APR than flexible products!", - { - projectId: z.string().describe("Locked product project ID"), - amount: z.number().positive().describe("Amount to subscribe"), - autoSubscribe: z.boolean().optional().describe("Auto-resubscribe when position matures"), - sourceAccount: z.enum(["SPOT", "FUND", "ALL"]).optional() - .describe("Source account for funds (default: SPOT)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.subscribeLockedProduct({ - projectId: params.projectId, - amount: params.amount, - ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), - ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + projectId: z.string().describe("Locked product project ID"), + amount: z.number().positive().describe("Amount to subscribe"), + autoSubscribe: z.boolean().optional().describe("Auto-resubscribe when position matures"), + sourceAccount: z + .enum(["SPOT", "FUND", "ALL"]) + .optional() + .describe("Source account for funds (default: SPOT)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.subscribeLockedProduct({ + projectId: params.projectId, + amount: params.amount, + ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), + ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Locked Product Subscription Successful!\n\nProject ID: ${params.projectId}\nAmount: ${params.amount}\nPosition ID: ${data.positionId || "N/A"}\n\n⚠️ Your funds are now locked. Rewards will be distributed based on the product terms.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Locked Product Subscription Successful!\n\nProject ID: ${params.projectId}\nAmount: ${params.amount}\nPosition ID: ${data.positionId || 'N/A'}\n\n⚠️ Your funds are now locked. Rewards will be distributed based on the product terms.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to subscribe to locked product: ${errorMessage}` - }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `❌ Failed to subscribe to locked product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/accountCommission.ts b/src/modules/spot/account-api/accountCommission.ts index 399bebdd..174c56f7 100644 --- a/src/modules/spot/account-api/accountCommission.ts +++ b/src/modules/spot/account-api/accountCommission.ts @@ -1,43 +1,47 @@ // src/tools/binance-spot/account-api/accountCommission.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAccountCommission(server: McpServer) { - server.tool( - "BinanceAccountCommission", - "Get account commission rates for a specific symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, recvWindow }) => { - try { - const params: any = { symbol }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.accountCommission(params); + server.registerTool( + "BinanceAccountCommission", + { + description: "Get account commission rates for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, recvWindow }) => { + try { + const params: any = { symbol }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.accountCommission(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved account commission rates for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account commission rates for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account commission rates: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve account commission rates: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/getAccount.ts b/src/modules/spot/account-api/getAccount.ts index c1339fa9..3aa498c8 100644 --- a/src/modules/spot/account-api/getAccount.ts +++ b/src/modules/spot/account-api/getAccount.ts @@ -1,42 +1,48 @@ -// src/tools/binance-spot/account-api/getAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { JSONStringify } from "json-with-bigint"; import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetAccount(server: McpServer) { - server.tool( - "BinanceGetAccount", - "Get current account information.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.getAccount(params); + server.registerTool( + "BinanceGetAccount", + { + description: "Get current account information.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = { + omitZeroBalances: true, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.getAccount(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved account information. Account contains ${data.balances?.length || 0} balances. Response: ${JSONStringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account information. Account contains ${data.balances?.length || 0} balances. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve account information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/index.ts b/src/modules/spot/account-api/index.ts index 6b1c4c10..53d31c2c 100644 --- a/src/modules/spot/account-api/index.ts +++ b/src/modules/spot/account-api/index.ts @@ -1,17 +1,18 @@ // src/tools/binance-spot/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceMyPreventedMatches } from "./myPreventedMatches.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountCommission } from "./accountCommission.js"; import { registerBinanceGetAccount } from "./getAccount.js"; import { registerBinanceMyAllocations } from "./myAllocations.js"; -import { registerBinanceRateLimitOrder } from "./rateLimitOrder.js"; -import { registerBinanceAccountCommission } from "./accountCommission.js"; +import { registerBinanceMyPreventedMatches } from "./myPreventedMatches.js"; import { registerBinanceMyTrades } from "./myTrades.js"; +import { registerBinanceRateLimitOrder } from "./rateLimitOrder.js"; export function registerBinanceAccountApiTools(server: McpServer) { - registerBinanceMyPreventedMatches(server); - registerBinanceGetAccount(server); - registerBinanceMyAllocations(server); - registerBinanceRateLimitOrder(server); - registerBinanceAccountCommission(server); - registerBinanceMyTrades(server); + registerBinanceMyPreventedMatches(server); + registerBinanceGetAccount(server); + registerBinanceMyAllocations(server); + registerBinanceRateLimitOrder(server); + registerBinanceAccountCommission(server); + registerBinanceMyTrades(server); } diff --git a/src/modules/spot/account-api/myAllocations.ts b/src/modules/spot/account-api/myAllocations.ts index 9d2bde83..672f5b92 100644 --- a/src/modules/spot/account-api/myAllocations.ts +++ b/src/modules/spot/account-api/myAllocations.ts @@ -1,52 +1,54 @@ // src/tools/binance-spot/account-api/myAllocations.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyAllocations(server: McpServer) { - server.tool( - "BinanceMyAllocations", - "Get SOR allocations for Self-Trade Prevention.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - allocationId: z.number().optional().describe("Allocation ID"), - orderId: z.number().optional().describe("Order ID"), - fromAllocationId: z.number().optional().describe("Allocation ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, allocationId, orderId, fromAllocationId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (allocationId !== undefined) params.allocationId = allocationId; - if (orderId !== undefined) params.orderId = orderId; - if (fromAllocationId !== undefined) params.fromAllocationId = fromAllocationId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myAllocations(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved SOR allocations for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve SOR allocations: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyAllocations", + { + description: "Get SOR allocations for Self-Trade Prevention.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + allocationId: z.number().optional().describe("Allocation ID"), + orderId: z.number().optional().describe("Order ID"), + fromAllocationId: z.number().optional().describe("Allocation ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, allocationId, orderId, fromAllocationId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (allocationId !== undefined) params.allocationId = allocationId; + if (orderId !== undefined) params.orderId = orderId; + if (fromAllocationId !== undefined) params.fromAllocationId = fromAllocationId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myAllocations(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved SOR allocations for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve SOR allocations: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/myPreventedMatches.ts b/src/modules/spot/account-api/myPreventedMatches.ts index c1ed4732..cb6e5e41 100644 --- a/src/modules/spot/account-api/myPreventedMatches.ts +++ b/src/modules/spot/account-api/myPreventedMatches.ts @@ -1,51 +1,56 @@ // src/tools/binance-spot/account-api/myPreventedMatches.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyPreventedMatches(server: McpServer) { - server.tool( - "BinanceMyPreventedMatches", - "Get prevented matches for Self-Trade Prevention.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - preventedMatchId: z.number().optional().describe("Prevented match ID"), - orderId: z.number().optional().describe("Order ID"), - fromPreventedMatchId: z.number().optional().describe("Prevented match ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, preventedMatchId, orderId, fromPreventedMatchId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (preventedMatchId !== undefined) params.preventedMatchId = preventedMatchId; - if (orderId !== undefined) params.orderId = orderId; - if (fromPreventedMatchId !== undefined) params.fromPreventedMatchId = fromPreventedMatchId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myPreventedMatches(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved prevented matches for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve prevented matches: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyPreventedMatches", + { + description: "Get prevented matches for Self-Trade Prevention.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + preventedMatchId: z.number().optional().describe("Prevented match ID"), + orderId: z.number().optional().describe("Order ID"), + fromPreventedMatchId: z.number().optional().describe("Prevented match ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, preventedMatchId, orderId, fromPreventedMatchId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (preventedMatchId !== undefined) params.preventedMatchId = preventedMatchId; + if (orderId !== undefined) params.orderId = orderId; + if (fromPreventedMatchId !== undefined) params.fromPreventedMatchId = fromPreventedMatchId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myPreventedMatches(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved prevented matches for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve prevented matches: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/myTrades.ts b/src/modules/spot/account-api/myTrades.ts index 450ffd23..9965ad2d 100644 --- a/src/modules/spot/account-api/myTrades.ts +++ b/src/modules/spot/account-api/myTrades.ts @@ -1,54 +1,56 @@ // src/tools/binance-spot/account-api/myTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyTrades(server: McpServer) { - server.tool( - "BinanceMyTrades", - "Get trades for a specific account and symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - fromId: z.number().optional().describe("Trade ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myTrades(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyTrades", + { + description: "Get trades for a specific account and symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve account trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/account-api/rateLimitOrder.ts b/src/modules/spot/account-api/rateLimitOrder.ts index a7886d3e..7eabceb3 100644 --- a/src/modules/spot/account-api/rateLimitOrder.ts +++ b/src/modules/spot/account-api/rateLimitOrder.ts @@ -1,42 +1,46 @@ // src/tools/binance-spot/account-api/rateLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceRateLimitOrder(server: McpServer) { - server.tool( - "BinanceRateLimitOrder", - "Get current order count usage for each rate limit.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.rateLimitOrder(params); + server.registerTool( + "BinanceRateLimitOrder", + { + description: "Get current order count usage for each rate limit.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.rateLimitOrder(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved current order count usage. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved current order count usage. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order count usage: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve order count usage: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/general-api/exchangeInfo.ts b/src/modules/spot/general-api/exchangeInfo.ts index 0c869f15..26b16df6 100644 --- a/src/modules/spot/general-api/exchangeInfo.ts +++ b/src/modules/spot/general-api/exchangeInfo.ts @@ -1,49 +1,67 @@ // src/tools/binance-spot/general-api/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceExchangeInfo(server: McpServer) { - server.tool( - "BinanceExchangeInfo", - "Get exchange information including rate limits, symbol configs, etc.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - symbols: z.array(z.string()).optional().describe("Array of symbols to get info for"), - permissions: z.array(z.string()).optional().describe("Array of permissions to filter by") - }, - async ({ symbol, symbols, permissions }) => { - try { - const params: any = {}; - - if (symbol) params.symbol = symbol; - if (symbols) params.symbols = symbols; - if (permissions) params.permissions = permissions; - - const response = await spotClient.restAPI.exchangeInfo(params); - - const data = await response.data(); - - const symbolCount = data.symbols?.length || 0; - const exchangeFiltersCount = data.exchangeFilters?.length || 0; - - return { - content: [ - { - type: "text", - text: `Retrieved exchange information. Total symbols: ${symbolCount}, Exchange filters: ${exchangeFiltersCount}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve exchange information: ${errorMessage}` } - ], - isError: true - }; - } + server.registerTool( + "BinanceExchangeInfo", + { + description: "Get exchange information including rate limits, symbol configs, etc.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Single trading pair in UPPERCASE, no separators (e.g. BTCUSDT, SOLUSDT). Use this for one pair; do not use both symbol and symbols.", + ), + symbols: z + .array(z.string()) + .optional() + .describe( + 'Multiple pairs as array; each symbol UPPERCASE (e.g. ["BTCUSDT","ETHUSDT"]). Do not use with symbol.', + ), + permissions: z.array(z.string()).optional().describe("Array of permissions to filter by"), + }, + }, + async ({ symbol, symbols, permissions }) => { + try { + const params: any = {}; + + if (symbol) params.symbol = symbol.toUpperCase(); + if (symbols?.length) { + params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); } - ); + if (permissions?.length && !params.symbol && !params.symbols) + params.permissions = permissions; + + const response = await (spotClient as any).restAPI.exchangeInfo(params); + + const data = await response.data(); + + const symbolCount = data.symbols?.length || 0; + const exchangeFiltersCount = data.exchangeFilters?.length || 0; + + return { + content: [ + { + type: "text", + text: `Retrieved exchange information. Total symbols: ${symbolCount}, Exchange filters: ${exchangeFiltersCount}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve exchange information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/general-api/index.ts b/src/modules/spot/general-api/index.ts index 5ba8ee07..3cecf4b7 100644 --- a/src/modules/spot/general-api/index.ts +++ b/src/modules/spot/general-api/index.ts @@ -1,12 +1,12 @@ // src/tools/binance-spot/general-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceExchangeInfo } from "./exchangeInfo.js"; import { registerBinancePing } from "./ping.js"; import { registerBinanceTime } from "./time.js"; -import { registerBinanceExchangeInfo } from "./exchangeInfo.js"; export function registerBinanceGeneralApiTools(server: McpServer) { - registerBinancePing(server); - registerBinanceTime(server); - registerBinanceExchangeInfo(server); - + registerBinancePing(server); + registerBinanceTime(server); + registerBinanceExchangeInfo(server); } diff --git a/src/modules/spot/general-api/ping.ts b/src/modules/spot/general-api/ping.ts index ee57842a..18939f88 100644 --- a/src/modules/spot/general-api/ping.ts +++ b/src/modules/spot/general-api/ping.ts @@ -1,37 +1,34 @@ // src/tools/binance-spot/general-api/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinancePing(server: McpServer) { - server.tool( - "BinancePing", - "Test connectivity to the Binance API.", - {}, - async () => { - try { - const response = await spotClient.restAPI.ping(); + server.registerTool( + "BinancePing", + { description: "Test connectivity to the Binance API." }, + async () => { + try { + const response = await (spotClient as any).restAPI.ping(); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully pinged Binance API. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully pinged Binance API. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to ping Binance API: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to ping Binance API: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/general-api/time.ts b/src/modules/spot/general-api/time.ts index cd6b4d18..bef51db8 100644 --- a/src/modules/spot/general-api/time.ts +++ b/src/modules/spot/general-api/time.ts @@ -1,34 +1,38 @@ // src/tools/binance-spot/general-api/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTime(server: McpServer) { - server.tool("BinanceTime", "Get the current server time from Binance API.", {}, async () => { - try { - const response = await spotClient.restAPI.time(); + server.registerTool( + "BinanceTime", + { description: "Get the current server time from Binance API." }, + async () => { + try { + const response = await (spotClient as any).restAPI.time(); + + const data = await response.data(); + + const serverTime = new Date(data.serverTime).toISOString(); - const data = await response.data(); - - //@ts-ignore - const serverTime = new Date(data.serverTime).toISOString(); + return { + content: [ + { + type: "text", + text: `Current Binance server time: ${serverTime} (${ + data.serverTime + }). Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Current Binance server time: ${serverTime} (${ - data.serverTime - }). Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to retrieve server time: ${errorMessage}` }], - isError: true - }; - } - }); + return { + content: [{ type: "text", text: `Failed to retrieve server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/index.ts b/src/modules/spot/index.ts index a9adb7c3..d87bcea7 100644 --- a/src/modules/spot/index.ts +++ b/src/modules/spot/index.ts @@ -1,27 +1,27 @@ // src/tools/binance-spot/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountApiTools } from "./account-api/index.js"; +import { registerBinanceGeneralApiTools } from "./general-api/index.js"; import { registerBinanceMarketApiTools } from "./market-api/index.js"; import { registerBinanceTradeApiTools } from "./trade-api/index.js"; -import { registerBinanceAccountApiTools } from "./account-api/index.js"; import { registerBinanceUserDataStreamApiTools } from "./userdatastream-api/index.js"; -import { registerBinanceGeneralApiTools } from "./general-api/index.js"; export function registerBinanceSpotTools(server: McpServer) { - // Trade API tools - registerBinanceTradeApiTools(server); - - // Market API tools - registerBinanceMarketApiTools(server); - - // Account API tools - registerBinanceAccountApiTools(server); - - // User Data Stream API tools - registerBinanceUserDataStreamApiTools(server); - - // General API tools - registerBinanceGeneralApiTools(server); - + // Trade API tools + registerBinanceTradeApiTools(server); + + // Market API tools + registerBinanceMarketApiTools(server); + + // Account API tools + registerBinanceAccountApiTools(server); + + // User Data Stream API tools + registerBinanceUserDataStreamApiTools(server); + + // General API tools + registerBinanceGeneralApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/spot/market-api/aggTrades.ts b/src/modules/spot/market-api/aggTrades.ts index 8c14bed9..1d1ef133 100644 --- a/src/modules/spot/market-api/aggTrades.ts +++ b/src/modules/spot/market-api/aggTrades.ts @@ -1,50 +1,52 @@ // src/tools/binance-spot/market-api/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAggTrades(server: McpServer) { - server.tool( - "BinanceAggTrades", - "Get compressed, aggregate trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - fromId: z.number().optional().describe("ID to get aggregate trades from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.aggTrades(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved aggregate trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve aggregate trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceAggTrades", + { + description: "Get compressed, aggregate trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + fromId: z.number().optional().describe("ID to get aggregate trades from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.aggTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved aggregate trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve aggregate trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/avgPrice.ts b/src/modules/spot/market-api/avgPrice.ts index 16107b77..4ccb304c 100644 --- a/src/modules/spot/market-api/avgPrice.ts +++ b/src/modules/spot/market-api/avgPrice.ts @@ -1,41 +1,43 @@ // src/tools/binance-spot/market-api/avgPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAvgPrice(server: McpServer) { - server.tool( - "BinanceAvgPrice", - "Get current average price for a trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const response = await spotClient.restAPI.avgPrice({ - symbol: symbol - }); + server.registerTool( + "BinanceAvgPrice", + { + description: "Get current average price for a trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const response = await (spotClient as any).restAPI.avgPrice({ + symbol: symbol, + }); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved current average price for ${symbol}. Average price: ${data.price}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved current average price for ${symbol}. Average price: ${data.price}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve average price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve average price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/depth.ts b/src/modules/spot/market-api/depth.ts index b83f84d5..2ce263f5 100644 --- a/src/modules/spot/market-api/depth.ts +++ b/src/modules/spot/market-api/depth.ts @@ -1,43 +1,45 @@ // src/tools/binance-spot/market-api/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDepth(server: McpServer) { - server.tool( - "BinanceDepth", - "Get order book depth data for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Depth of the order book. Default 100; max 5000.") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.depth(params); + server.registerTool( + "BinanceDepth", + { + description: "Get order book depth data for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Depth of the order book. Default 100; max 5000."), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.depth(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order book depth: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve order book depth: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/getTrades.ts b/src/modules/spot/market-api/getTrades.ts index 7c885045..2ecffd7e 100644 --- a/src/modules/spot/market-api/getTrades.ts +++ b/src/modules/spot/market-api/getTrades.ts @@ -1,43 +1,46 @@ // src/tools/binance-spot/market-api/getTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetTrades(server: McpServer) { - server.tool( - "BinanceGetTrades", - "Get recent trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.getTrades(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved recent trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve recent trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceGetTrades", + { + description: "Get recent trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.getTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved recent trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve recent trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/historicalTrades.ts b/src/modules/spot/market-api/historicalTrades.ts index cefd0378..4ac08777 100644 --- a/src/modules/spot/market-api/historicalTrades.ts +++ b/src/modules/spot/market-api/historicalTrades.ts @@ -1,45 +1,50 @@ // src/tools/binance-spot/market-api/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceHistoricalTrades(server: McpServer) { - server.tool( - "BinanceHistoricalTrades", - "Get older historical trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Default 500; max 1000"), - fromId: z.number().optional().describe("Trade ID to fetch from") - }, - async ({ symbol, limit, fromId }) => { - try { - const params: any = { symbol }; - - if (limit !== undefined) params.limit = limit; - if (fromId !== undefined) params.fromId = fromId; - - const response = await spotClient.restAPI.historicalTrades(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved historical trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve historical trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceHistoricalTrades", + { + description: "Get older historical trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Default 500; max 1000"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + }, + }, + async ({ symbol, limit, fromId }) => { + try { + const params: any = { symbol }; + + if (limit !== undefined) params.limit = limit; + if (fromId !== undefined) params.fromId = fromId; + + const response = await (spotClient as any).restAPI.historicalTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved historical trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve historical trades: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/index.ts b/src/modules/spot/market-api/index.ts index b0730073..51efb908 100644 --- a/src/modules/spot/market-api/index.ts +++ b/src/modules/spot/market-api/index.ts @@ -1,30 +1,30 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAggTrades } from "./aggTrades.js"; +import { registerBinanceAvgPrice } from "./avgPrice.js"; +import { registerBinanceDepth } from "./depth.js"; +import { registerBinanceGetTrades } from "./getTrades.js"; +import { registerBinanceHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceKlines } from "./klines.js"; import { registerBinanceTicker24hr } from "./ticker24hr.js"; -import { registerBinanceDepth } from "./depth.js"; -import { registerBinanceAggTrades } from "./aggTrades.js"; -import { registerBinanceTickerTradingDay } from "./tickerTradingDay.js"; -import { registerBinanceUiKlines } from "./uiKlines.js"; +import { registerBinanceTicker } from "./ticker.js"; import { registerBinanceTickerBookTicker } from "./tickerBookTicker.js"; -import { registerBinanceAvgPrice } from "./avgPrice.js"; import { registerBinanceTickerPrice } from "./tickerPrice.js"; -import { registerBinanceTicker } from "./ticker.js"; -import { registerBinanceHistoricalTrades } from "./historicalTrades.js"; -import { registerBinanceGetTrades } from "./getTrades.js"; +import { registerBinanceTickerTradingDay } from "./tickerTradingDay.js"; +import { registerBinanceUiKlines } from "./uiKlines.js"; export function registerBinanceMarketApiTools(server: McpServer) { - registerBinanceKlines(server); - registerBinanceTicker24hr(server); - registerBinanceDepth(server); - registerBinanceAggTrades(server); - registerBinanceTickerTradingDay(server); - registerBinanceUiKlines(server); - registerBinanceTickerBookTicker(server); - registerBinanceAvgPrice(server); - registerBinanceTickerPrice(server); - registerBinanceTicker(server); - registerBinanceHistoricalTrades(server); - registerBinanceGetTrades(server); - -} \ No newline at end of file + registerBinanceKlines(server); + registerBinanceTicker24hr(server); + registerBinanceDepth(server); + registerBinanceAggTrades(server); + registerBinanceTickerTradingDay(server); + registerBinanceUiKlines(server); + registerBinanceTickerBookTicker(server); + registerBinanceAvgPrice(server); + registerBinanceTickerPrice(server); + registerBinanceTicker(server); + registerBinanceHistoricalTrades(server); + registerBinanceGetTrades(server); +} diff --git a/src/modules/spot/market-api/klines.ts b/src/modules/spot/market-api/klines.ts index 53e3fcf5..69ee69df 100644 --- a/src/modules/spot/market-api/klines.ts +++ b/src/modules/spot/market-api/klines.ts @@ -1,53 +1,72 @@ // src/tools/binance-spot/market-api/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceKlines(server: McpServer) { - server.tool( - "BinanceKlines", - "Get candlestick data (klines) for a specific trading pair and interval.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { - symbol, - interval - }; - - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.klines(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceKlines", + { + description: "Get candlestick data (klines) for a specific trading pair and interval.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { + symbol, + interval, + }; + + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.klines(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/ticker.ts b/src/modules/spot/market-api/ticker.ts index 12e44187..085fb0a9 100644 --- a/src/modules/spot/market-api/ticker.ts +++ b/src/modules/spot/market-api/ticker.ts @@ -1,49 +1,57 @@ // src/tools/binance-spot/market-api/ticker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTicker(server: McpServer) { - server.tool( - "BinanceTicker", + server.registerTool( + "BinanceTicker", + { + description: "Get 24-hour rolling window price change statistics for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - windowSize: z.string().optional().describe("Defaults to 1d. Valid values: 1d, 2d, 3d, 4d, 5d, 6d, 7d") - }, - async ({ symbol, windowSize }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (windowSize) params.windowSize = windowSize; - - const response = await spotClient.restAPI.ticker(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved ticker statistics for all symbols${windowSize ? ` with window size ${windowSize}` : ''}. Total items: ${data.length}.` - : `Retrieved ticker statistics for ${symbol}${windowSize ? ` with window size ${windowSize}` : ''}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve ticker statistics: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + windowSize: z + .string() + .optional() + .describe("Defaults to 1d. Valid values: 1d, 2d, 3d, 4d, 5d, 6d, 7d"), + }, + }, + async ({ symbol, windowSize }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (windowSize) params.windowSize = windowSize; + + const response = await (spotClient as any).restAPI.ticker(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved ticker statistics for all symbols${windowSize ? ` with window size ${windowSize}` : ""}. Total items: ${data.length}.` + : `Retrieved ticker statistics for ${symbol}${windowSize ? ` with window size ${windowSize}` : ""}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve ticker statistics: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/ticker24hr.ts b/src/modules/spot/market-api/ticker24hr.ts index 12ddce0d..35d607fb 100644 --- a/src/modules/spot/market-api/ticker24hr.ts +++ b/src/modules/spot/market-api/ticker24hr.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTicker24hr(server: McpServer) { - server.tool( - "BinanceTicker24hr", - "Get 24-hour price change statistics for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.ticker24hr(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved 24hr statistics for all symbols. Total items: ${data.length}.` - : `Retrieved 24hr statistics for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve 24hr ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTicker24hr", + { + description: "Get 24-hour price change statistics for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.ticker24hr(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved 24hr statistics for all symbols. Total items: ${data.length}.` + : `Retrieved 24hr statistics for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve 24hr ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/tickerBookTicker.ts b/src/modules/spot/market-api/tickerBookTicker.ts index 44a28791..103c86fb 100644 --- a/src/modules/spot/market-api/tickerBookTicker.ts +++ b/src/modules/spot/market-api/tickerBookTicker.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/tickerBookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerBookTicker(server: McpServer) { - server.tool( - "BinanceTickerBookTicker", - "Get best price/quantity on the order book for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerBookTicker(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved best price/quantity on the order book for all symbols. Total items: ${data.length}.` - : `Retrieved best price/quantity on the order book for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve book ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerBookTicker", + { + description: "Get best price/quantity on the order book for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerBookTicker(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved best price/quantity on the order book for all symbols. Total items: ${data.length}.` + : `Retrieved best price/quantity on the order book for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve book ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/tickerPrice.ts b/src/modules/spot/market-api/tickerPrice.ts index 98313726..7a4ee56f 100644 --- a/src/modules/spot/market-api/tickerPrice.ts +++ b/src/modules/spot/market-api/tickerPrice.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerPrice(server: McpServer) { - server.tool( - "BinanceTickerPrice", - "Get latest price for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerPrice(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved latest prices for all symbols. Total items: ${data.length}.` - : `Retrieved latest price for ${symbol}: ${data.price}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve ticker price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerPrice", + { + description: "Get latest price for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerPrice(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved latest prices for all symbols. Total items: ${data.length}.` + : `Retrieved latest price for ${symbol}: ${data.price}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve ticker price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/tickerTradingDay.ts b/src/modules/spot/market-api/tickerTradingDay.ts index 7d96249e..0f43c545 100644 --- a/src/modules/spot/market-api/tickerTradingDay.ts +++ b/src/modules/spot/market-api/tickerTradingDay.ts @@ -1,47 +1,51 @@ // src/tools/binance-spot/market-api/tickerTradingDay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerTradingDay(server: McpServer) { - server.tool( - "BinanceTickerTradingDay", - "Get statistics for the current trading day for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerTradingDay(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved trading day statistics for all symbols. Total items: ${data.length}.` - : `Retrieved trading day statistics for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve trading day statistics: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerTradingDay", + { + description: "Get statistics for the current trading day for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerTradingDay(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved trading day statistics for all symbols. Total items: ${data.length}.` + : `Retrieved trading day statistics for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve trading day statistics: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/market-api/uiKlines.ts b/src/modules/spot/market-api/uiKlines.ts index 96100d2b..9a767f00 100644 --- a/src/modules/spot/market-api/uiKlines.ts +++ b/src/modules/spot/market-api/uiKlines.ts @@ -1,53 +1,72 @@ // src/tools/binance-spot/market-api/uiKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceUiKlines(server: McpServer) { - server.tool( - "BinanceUiKlines", - "Get UI-optimized candlestick data for a specific trading pair and interval.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { - symbol, - interval - }; - - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.uiKlines(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved UI klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve UI klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceUiKlines", + { + description: "Get UI-optimized candlestick data for a specific trading pair and interval.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { + symbol, + interval, + }; + + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.uiKlines(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved UI klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve UI klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/allOrders.ts b/src/modules/spot/trade-api/allOrders.ts index d94ac840..41dcc20d 100644 --- a/src/modules/spot/trade-api/allOrders.ts +++ b/src/modules/spot/trade-api/allOrders.ts @@ -1,49 +1,55 @@ // src/tools/binance-spot/trade-api/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAllOrders(server: McpServer) { - server.tool( - "BinanceAllOrders", - "Get all account orders for a specific symbol; active, canceled, or filled.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID to start from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Maximum number of orders to return (default 500, max 1000)") - }, - async ({ symbol, orderId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.allOrders(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved all orders for ${symbol}. Total orders: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve all orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceAllOrders", + { + description: "Get all account orders for a specific symbol; active, canceled, or filled.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID to start from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z + .number() + .optional() + .describe("Maximum number of orders to return (default 500, max 1000)"), + }, + }, + async ({ symbol, orderId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.allOrders(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved all orders for ${symbol}. Total orders: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/deleteOpenOrders.ts b/src/modules/spot/trade-api/deleteOpenOrders.ts index 1cdaca3f..541b9de6 100644 --- a/src/modules/spot/trade-api/deleteOpenOrders.ts +++ b/src/modules/spot/trade-api/deleteOpenOrders.ts @@ -1,40 +1,43 @@ // src/tools/binance-spot/trade-api/deleteOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteOpenOrders(server: McpServer) { - server.tool( - "BinanceDeleteOpenOrders", - "Cancel all open orders on Binance for a specific symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const response = await spotClient.restAPI.deleteOpenOrders({ - symbol: symbol - }); + server.registerTool( + "BinanceDeleteOpenOrders", + { + description: "Cancel all open orders on Binance for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const response = await (spotClient as any).restAPI.deleteOpenOrders({ + symbol: symbol, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully canceled all open orders for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully canceled all open orders for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to cancel open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/deleteOrder.ts b/src/modules/spot/trade-api/deleteOrder.ts index 027bdde0..ac8036f0 100644 --- a/src/modules/spot/trade-api/deleteOrder.ts +++ b/src/modules/spot/trade-api/deleteOrder.ts @@ -1,45 +1,48 @@ // src/tools/binance-spot/trade-api/deleteOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteOrder(server: McpServer) { - server.tool( - "BinanceDeleteOrder", - "Cancel an active order on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.string().optional().describe("The order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - - if (orderId) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; - - const response = await spotClient.restAPI.deleteOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Order successfully canceled. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceDeleteOrder", + { + description: "Cancel an active order on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.string().optional().describe("The order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + + if (orderId) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const response = await (spotClient as any).restAPI.deleteOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Order successfully canceled. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/getOpenOrders.ts b/src/modules/spot/trade-api/getOpenOrders.ts index 0f129727..9d36a0ad 100644 --- a/src/modules/spot/trade-api/getOpenOrders.ts +++ b/src/modules/spot/trade-api/getOpenOrders.ts @@ -1,41 +1,44 @@ // src/tools/binance-spot/trade-api/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetOpenOrders(server: McpServer) { - server.tool( - "BinanceGetOpenOrders", - "Get all open orders on Binance for a specific symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.getOpenOrders(params); + server.registerTool( + "BinanceGetOpenOrders", + { + description: "Get all open orders on Binance for a specific symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.getOpenOrders(params); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved open orders${symbol ? ` for ${symbol}` : ""}. Total open orders: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open orders${symbol ? ` for ${symbol}` : ''}. Total open orders: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/getOrder.ts b/src/modules/spot/trade-api/getOrder.ts index e7647207..3357bf2b 100644 --- a/src/modules/spot/trade-api/getOrder.ts +++ b/src/modules/spot/trade-api/getOrder.ts @@ -1,45 +1,50 @@ // src/tools/binance-spot/trade-api/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetOrder(server: McpServer) { - server.tool( - "BinanceGetOrder", - "Check an order's status on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.string().optional().describe("The order ID to query"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - - if (orderId) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; - - const response = await spotClient.restAPI.getOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Order information retrieved successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceGetOrder", + { + description: "Check an order's status on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.string().optional().describe("The order ID to query"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + + if (orderId) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const response = await (spotClient as any).restAPI.getOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Order information retrieved successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve order information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/index.ts b/src/modules/spot/trade-api/index.ts index 1478bdd3..dac0fe57 100644 --- a/src/modules/spot/trade-api/index.ts +++ b/src/modules/spot/trade-api/index.ts @@ -1,22 +1,22 @@ // src/tools/binance-spot/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDeleteOrder } from "./deleteOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceAllOrders } from "./allOrders.js"; -import { registerBinanceOpenOrderList } from "./openOrderList.js"; -import { registerBinanceNewOrder } from "./newOrder.js"; -import { registerBinanceGetOrder } from "./getOrder.js"; -import { registerBinanceGetOpenOrders } from "./getOpenOrders.js"; import { registerBinanceDeleteOpenOrders } from "./deleteOpenOrders.js"; +import { registerBinanceDeleteOrder } from "./deleteOrder.js"; +import { registerBinanceGetOpenOrders } from "./getOpenOrders.js"; +import { registerBinanceGetOrder } from "./getOrder.js"; +import { registerBinanceNewOrder } from "./newOrder.js"; +import { registerBinanceOpenOrderList } from "./openOrderList.js"; import { registerBinanceOrderOco } from "./orderOco.js"; export function registerBinanceTradeApiTools(server: McpServer) { - registerBinanceDeleteOrder(server); - registerBinanceAllOrders(server); - registerBinanceOpenOrderList(server); - registerBinanceNewOrder(server); - registerBinanceGetOrder(server); - registerBinanceGetOpenOrders(server); - registerBinanceDeleteOpenOrders(server); - registerBinanceOrderOco(server); - -} \ No newline at end of file + registerBinanceDeleteOrder(server); + registerBinanceAllOrders(server); + registerBinanceOpenOrderList(server); + registerBinanceNewOrder(server); + registerBinanceGetOrder(server); + registerBinanceGetOpenOrders(server); + registerBinanceDeleteOpenOrders(server); + registerBinanceOrderOco(server); +} diff --git a/src/modules/spot/trade-api/newOrder.ts b/src/modules/spot/trade-api/newOrder.ts index 1b01cfe5..e62eb377 100644 --- a/src/modules/spot/trade-api/newOrder.ts +++ b/src/modules/spot/trade-api/newOrder.ts @@ -1,63 +1,102 @@ // src/tools/binance-spot/trade-api/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; +/** Binance allows only [a-zA-Z0-9-_], max 36 chars. */ +function sanitizeNewClientOrderId(value: string): string { + return value.replace(/[^a-zA-Z0-9-_]/g, "").slice(0, 36); +} + export function registerBinanceNewOrder(server: McpServer) { - server.tool( - "BinanceNewOrder", - "Create a new order on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), - type: z.enum(["LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]).describe("Order type"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - quantity: z.number().describe("Order quantity"), - quoteOrderQty: z.number().optional().describe("Quote order quantity"), - price: z.number().optional().describe("Order price"), - newClientOrderId: z.string().optional().describe("Client order ID"), - stopPrice: z.number().optional().describe("Stop price"), - icebergQty: z.number().optional().describe("Iceberg quantity"), - newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type") - }, - async ({ symbol, side, type, timeInForce, quantity, quoteOrderQty, price, newClientOrderId, stopPrice, icebergQty, newOrderRespType }) => { - try { - const params: any = { - symbol, - side, - type, - quantity - }; - - if (timeInForce) params.timeInForce = timeInForce; - if (quoteOrderQty !== undefined) params.quoteOrderQty = quoteOrderQty; - if (price !== undefined) params.price = price; - if (newClientOrderId) params.newClientOrderId = newClientOrderId; - if (stopPrice !== undefined) params.stopPrice = stopPrice; - if (icebergQty !== undefined) params.icebergQty = icebergQty; - if (newOrderRespType) params.newOrderRespType = newOrderRespType; - - const response = await spotClient.restAPI.newOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `New order successfully created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create new order: ${errorMessage}` } - ], - isError: true - }; - } + server.registerTool( + "BinanceNewOrder", + { + description: "Create a new order on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", + ]) + .describe("Order type"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + quantity: z.number().describe("Order quantity"), + quoteOrderQty: z.number().optional().describe("Quote order quantity"), + price: z.number().optional().describe("Order price"), + newClientOrderId: z + .string() + .optional() + .describe("Client order ID: only a-zA-Z0-9-_ allowed, max 36 chars"), + stopPrice: z.number().optional().describe("Stop price"), + icebergQty: z.number().optional().describe("Iceberg quantity"), + newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), + }, + }, + async ({ + symbol, + side, + type, + timeInForce, + quantity, + quoteOrderQty, + price, + newClientOrderId, + stopPrice, + icebergQty, + newOrderRespType, + }) => { + try { + const params: any = { + symbol, + side, + type, + quantity, + }; + + const timeInForceTypes = ["LIMIT", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]; + if (timeInForce && timeInForceTypes.includes(type)) params.timeInForce = timeInForce; + if (type === "MARKET" && quoteOrderQty !== undefined) params.quoteOrderQty = quoteOrderQty; + const priceTypes = ["LIMIT", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]; + if (price !== undefined && priceTypes.includes(type)) params.price = price; + if (newClientOrderId) { + const sanitized = sanitizeNewClientOrderId(newClientOrderId); + if (sanitized) params.newClientOrderId = sanitized; } - ); -} \ No newline at end of file + const stopOrderTypes = ["STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT"]; + if (stopPrice !== undefined && stopOrderTypes.includes(type)) params.stopPrice = stopPrice; + if (icebergQty !== undefined) params.icebergQty = icebergQty; + if (newOrderRespType) params.newOrderRespType = newOrderRespType; + + const response = await (spotClient as any).restAPI.newOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `New order successfully created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create new order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/openOrderList.ts b/src/modules/spot/trade-api/openOrderList.ts index 7c6134f5..02ae7c12 100644 --- a/src/modules/spot/trade-api/openOrderList.ts +++ b/src/modules/spot/trade-api/openOrderList.ts @@ -1,41 +1,44 @@ // src/tools/binance-spot/trade-api/openOrderList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceOpenOrderList(server: McpServer) { - server.tool( - "BinanceOpenOrderList", - "Query open OCO orders for a specific account or symbol.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.openOrderList(params); + server.registerTool( + "BinanceOpenOrderList", + { + description: "Query open OCO orders for a specific account or symbol.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.openOrderList(params); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved open OCO orders${symbol ? ` for ${symbol}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open OCO orders${symbol ? ` for ${symbol}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open OCO orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open OCO orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/trade-api/orderOco.ts b/src/modules/spot/trade-api/orderOco.ts index b758bf40..b3e09c8e 100644 --- a/src/modules/spot/trade-api/orderOco.ts +++ b/src/modules/spot/trade-api/orderOco.ts @@ -1,63 +1,81 @@ // src/tools/binance-spot/trade-api/orderOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceOrderOco(server: McpServer) { - server.tool( - "BinanceOrderOco", - "Send a new OCO (One-Cancels-the-Other) order on Binance.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), - quantity: z.number().describe("Order quantity"), - price: z.number().describe("Order price"), - stopPrice: z.number().describe("Stop price"), - stopLimitPrice: z.number().optional().describe("Stop limit price"), - stopLimitTimeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Stop limit time in force"), - newClientOrderId: z.string().optional().describe("Client order ID for the limit order"), - stopClientOrderId: z.string().optional().describe("Client order ID for the stop order"), - limitIcebergQty: z.number().optional().describe("Limit iceberg quantity"), - stopIcebergQty: z.number().optional().describe("Stop iceberg quantity") - }, - async ({ symbol, side, quantity, price, stopPrice, stopLimitPrice, stopLimitTimeInForce, newClientOrderId, stopClientOrderId, limitIcebergQty, stopIcebergQty }) => { - try { - const params: any = { - symbol, - side, - quantity, - price, - stopPrice - }; - - if (stopLimitPrice !== undefined) params.stopLimitPrice = stopLimitPrice; - if (stopLimitTimeInForce) params.stopLimitTimeInForce = stopLimitTimeInForce; - if (newClientOrderId) params.newClientOrderId = newClientOrderId; - if (stopClientOrderId) params.stopClientOrderId = stopClientOrderId; - if (limitIcebergQty !== undefined) params.limitIcebergQty = limitIcebergQty; - if (stopIcebergQty !== undefined) params.stopIcebergQty = stopIcebergQty; - - const response = await spotClient.restAPI.orderOco(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `OCO order successfully created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create OCO order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceOrderOco", + { + description: "Send a new OCO (One-Cancels-the-Other) order on Binance.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), + quantity: z.number().describe("Order quantity"), + price: z.number().describe("Order price"), + stopPrice: z.number().describe("Stop price"), + stopLimitPrice: z.number().optional().describe("Stop limit price"), + stopLimitTimeInForce: z + .enum(["GTC", "IOC", "FOK"]) + .optional() + .describe("Stop limit time in force"), + newClientOrderId: z.string().optional().describe("Client order ID for the limit order"), + stopClientOrderId: z.string().optional().describe("Client order ID for the stop order"), + limitIcebergQty: z.number().optional().describe("Limit iceberg quantity"), + stopIcebergQty: z.number().optional().describe("Stop iceberg quantity"), + }, + }, + async ({ + symbol, + side, + quantity, + price, + stopPrice, + stopLimitPrice, + stopLimitTimeInForce, + newClientOrderId, + stopClientOrderId, + limitIcebergQty, + stopIcebergQty, + }) => { + try { + const params: any = { + symbol, + side, + quantity, + price, + stopPrice, + }; + + if (stopLimitPrice !== undefined) params.stopLimitPrice = stopLimitPrice; + if (stopLimitTimeInForce) params.stopLimitTimeInForce = stopLimitTimeInForce; + if (newClientOrderId) params.newClientOrderId = newClientOrderId; + if (stopClientOrderId) params.stopClientOrderId = stopClientOrderId; + if (limitIcebergQty !== undefined) params.limitIcebergQty = limitIcebergQty; + if (stopIcebergQty !== undefined) params.stopIcebergQty = stopIcebergQty; + + const response = await (spotClient as any).restAPI.orderOco(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `OCO order successfully created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/spot/userdatastream-api/deleteUserDataStream.ts b/src/modules/spot/userdatastream-api/deleteUserDataStream.ts index 7f6001f4..5dfa7052 100644 --- a/src/modules/spot/userdatastream-api/deleteUserDataStream.ts +++ b/src/modules/spot/userdatastream-api/deleteUserDataStream.ts @@ -1,40 +1,43 @@ // src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteUserDataStream(server: McpServer) { - server.tool( - "BinanceDeleteUserDataStream", - "Close a user data stream by invalidating the listen key.", - { - listenKey: z.string().describe("Listen key to close") - }, - async ({ listenKey }) => { - try { - const response = await spotClient.restAPI.deleteUserDataStream({ - listenKey: listenKey - }); + server.registerTool( + "BinanceDeleteUserDataStream", + { + description: "Close a user data stream by invalidating the listen key.", + inputSchema: { + listenKey: z.string().describe("Listen key to close"), + }, + }, + async ({ listenKey }) => { + try { + const response = await (spotClient as any).restAPI.deleteUserDataStream({ + listenKey: listenKey, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully closed user data stream with listen key: ${listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully closed user data stream with listen key: ${listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to close user data stream: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to close user data stream: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/userdatastream-api/index.ts b/src/modules/spot/userdatastream-api/index.ts index f6e3f61c..288eaa88 100644 --- a/src/modules/spot/userdatastream-api/index.ts +++ b/src/modules/spot/userdatastream-api/index.ts @@ -1,12 +1,12 @@ // src/tools/binance-spot/userdatastream-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceNewUserDataStream } from "./newUserDataStream.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDeleteUserDataStream } from "./deleteUserDataStream.js"; +import { registerBinanceNewUserDataStream } from "./newUserDataStream.js"; import { registerBinancePutUserDataStream } from "./putUserDataStream.js"; export function registerBinanceUserDataStreamApiTools(server: McpServer) { - registerBinanceNewUserDataStream(server); - registerBinanceDeleteUserDataStream(server); - registerBinancePutUserDataStream(server); - + registerBinanceNewUserDataStream(server); + registerBinanceDeleteUserDataStream(server); + registerBinancePutUserDataStream(server); } diff --git a/src/modules/spot/userdatastream-api/newUserDataStream.ts b/src/modules/spot/userdatastream-api/newUserDataStream.ts index 767167dd..74dd45f0 100644 --- a/src/modules/spot/userdatastream-api/newUserDataStream.ts +++ b/src/modules/spot/userdatastream-api/newUserDataStream.ts @@ -1,36 +1,34 @@ // src/tools/binance-spot/userdatastream-api/newUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceNewUserDataStream(server: McpServer) { - server.tool( - "BinanceNewUserDataStream", - "Create a new user data stream to receive account updates via WebSocket.", - {}, - async () => { - try { - const response = await spotClient.restAPI.newUserDataStream(); + server.registerTool( + "BinanceNewUserDataStream", + { description: "Create a new user data stream to receive account updates via WebSocket." }, + async () => { + try { + const response = await (spotClient as any).restAPI.newUserDataStream(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Created new listen key for user data stream. Listen key: ${data.listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Created new listen key for user data stream. Listen key: ${data.listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create user data stream: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to create user data stream: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/spot/userdatastream-api/putUserDataStream.ts b/src/modules/spot/userdatastream-api/putUserDataStream.ts index 4e05e565..63568ebe 100644 --- a/src/modules/spot/userdatastream-api/putUserDataStream.ts +++ b/src/modules/spot/userdatastream-api/putUserDataStream.ts @@ -1,40 +1,45 @@ // src/tools/binance-spot/userdatastream-api/putUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinancePutUserDataStream(server: McpServer) { - server.tool( - "BinancePutUserDataStream", - "Extend the validity of a user data stream listen key.", - { - listenKey: z.string().describe("Listen key to keep alive") - }, - async ({ listenKey }) => { - try { - const response = await spotClient.restAPI.putUserDataStream({ - listenKey: listenKey - }); + server.registerTool( + "BinancePutUserDataStream", + { + description: "Extend the validity of a user data stream listen key.", + inputSchema: { + listenKey: z.string().describe("Listen key to keep alive"), + }, + }, + async ({ listenKey }) => { + try { + const response = await (spotClient as any).restAPI.putUserDataStream({ + listenKey: listenKey, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully extended validity of listen key: ${listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully extended validity of listen key: ${listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to extend listen key validity: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to extend listen key validity: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/ethStakingAccount.ts b/src/modules/staking/ETH-staking-api/ethStakingAccount.ts index aeff9941..cad0c72b 100644 --- a/src/modules/staking/ETH-staking-api/ethStakingAccount.ts +++ b/src/modules/staking/ETH-staking-api/ethStakingAccount.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceEthStakingAccount(server: McpServer) { - server.tool( - "BinanceEthStakingAccount", + server.registerTool( + "BinanceEthStakingAccount", + { + description: "ETH Staking Account API allows users to retrieve their current ETH staking holdings and 30-day profit details, including amounts from WBETH and BETH", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.ethStakingAccount({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.ethStakingAccount({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current ETH staking holdings . Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current ETH staking holdings . Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve ETH staking holdings . ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve ETH staking holdings . ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getCurrentEthStakingQuota.ts b/src/modules/staking/ETH-staking-api/getCurrentEthStakingQuota.ts index ed542bda..7275a607 100644 --- a/src/modules/staking/ETH-staking-api/getCurrentEthStakingQuota.ts +++ b/src/modules/staking/ETH-staking-api/getCurrentEthStakingQuota.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetCurrentEthStakingQuota(server: McpServer) { - server.tool( - "BinanceGetCurrentEthStakingQuota", + server.registerTool( + "BinanceGetCurrentEthStakingQuota", + { + description: "Get Current ETH Staking Quota API allows users to retrieve their available ETH staking and redemption quotas, reflecting personal and daily limits.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current ETH Staking Quota API allows users. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current ETH Staking Quota API allows users. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve current ETH Staking Quota API allows users. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve current ETH Staking Quota API allows users. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getEthRedemptionHistory.ts b/src/modules/staking/ETH-staking-api/getEthRedemptionHistory.ts index 4f86c09c..98eeae75 100644 --- a/src/modules/staking/ETH-staking-api/getEthRedemptionHistory.ts +++ b/src/modules/staking/ETH-staking-api/getEthRedemptionHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetEthRedemptionHistory(server: McpServer) { - server.tool( - "BinanceGetEthRedemptionHistory", + server.registerTool( + "BinanceGetEthRedemptionHistory", + { + description: "Get ETH Redemption History API allows users to retrieve their historical ETH staking redemption records, including details like asset type, amount, status, and time of redemption.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page, start from 1. Default is 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page, Default is 10, Max is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page, start from 1. Default is 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page, Default is 10, Max is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved history API allows users to retrieve their historical ETH staking redemption records. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved history API allows users to retrieve their historical ETH staking redemption records. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve history API allows users to retrieve their historical ETH staking redemption records. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve history API allows users to retrieve their historical ETH staking redemption records. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getEthStakingHistory.ts b/src/modules/staking/ETH-staking-api/getEthStakingHistory.ts index e93d94d9..e41ef5ac 100644 --- a/src/modules/staking/ETH-staking-api/getEthStakingHistory.ts +++ b/src/modules/staking/ETH-staking-api/getEthStakingHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetEthStakingHistory(server: McpServer) { - server.tool( - "registerBinanceGetEthStakingHistory", + server.registerTool( + "registerBinanceGetEthStakingHistory", + { + description: "Get ETH Staking History API allows users to retrieve their historical ETH staking records, including details like asset type, amount, status, and time of staking", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default is 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default is 10, Max is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getEthStakingHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default is 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default is 10, Max is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getEthStakingHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved ETH Staking History API allows users to retrieve their historical ETH staking records. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved ETH Staking History API allows users to retrieve their historical ETH staking records. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve ETH Staking History API allows users to retrieve their historical ETH staking records. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve ETH Staking History API allows users to retrieve their historical ETH staking records. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getWbethRateHistory.ts b/src/modules/staking/ETH-staking-api/getWbethRateHistory.ts index d54febd0..e2c1056e 100644 --- a/src/modules/staking/ETH-staking-api/getWbethRateHistory.ts +++ b/src/modules/staking/ETH-staking-api/getWbethRateHistory.ts @@ -1,67 +1,77 @@ // src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethRateHistory(server: McpServer) { - server.tool( - "BinanceGetWbethRateHistory", + server.registerTool( + "BinanceGetWbethRateHistory", + { + description: "Get WBETH Rate History API allows users to retrieve historical WBETH exchange rates and BETH annual percentage rates (APR) within a specified time range.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Starts from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + + recvWindow: z + .number() + .int() + .optional() + .describe("Time window for request validity (in milliseconds)"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethRateHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); - recvWindow: z.number().int().optional().describe("Time window for request validity (in milliseconds)") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethRateHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical WBETH exchange rates and BETH annual percentage rates. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical WBETH exchange rates and BETH annual percentage rates. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical WBETH exchange rates and BETH annual percentage rates. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical WBETH exchange rates and BETH annual percentage rates. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getWbethRewardsHistory.ts b/src/modules/staking/ETH-staking-api/getWbethRewardsHistory.ts index e0c06400..a02a08ff 100644 --- a/src/modules/staking/ETH-staking-api/getWbethRewardsHistory.ts +++ b/src/modules/staking/ETH-staking-api/getWbethRewardsHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetWbethRewardsHistory", + server.registerTool( + "BinanceGetWbethRewardsHistory", + { + description: "Get WBETH Rewards History API allows users to retrieve historical reward data earned from WBETH holdings, including estimated rewards in ETH, holding amounts, and APR details.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522720000)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethRewardsHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522720000)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethRewardsHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical reward data earned from WBETH holdings. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical reward data earned from WBETH holdings. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical reward data earned from WBETH holdings. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical reward data earned from WBETH holdings. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getWbethUnwrapHistory.ts b/src/modules/staking/ETH-staking-api/getWbethUnwrapHistory.ts index 9167ac06..12fcdb90 100644 --- a/src/modules/staking/ETH-staking-api/getWbethUnwrapHistory.ts +++ b/src/modules/staking/ETH-staking-api/getWbethUnwrapHistory.ts @@ -1,66 +1,76 @@ // src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethUnwrapHistory(server: McpServer) { - server.tool( - "BinanceGetWbethUnwrapHistory", + server.registerTool( + "BinanceGetWbethUnwrapHistory", + { + description: "Get WBETH Unwrap History API allows users to retrieve historical records of WBETH unwrap operations, including asset conversion details, exchange rates, and transaction status.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity (in milliseconds)") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethUnwrapHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Time window for request validity (in milliseconds)"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethUnwrapHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical records of WBETH unwrap operations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical records of WBETH unwrap operations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical records of WBETH unwrap operations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical records of WBETH unwrap operations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/getWbethWrapHistory.ts b/src/modules/staking/ETH-staking-api/getWbethWrapHistory.ts index e6295b81..5b69ef1d 100644 --- a/src/modules/staking/ETH-staking-api/getWbethWrapHistory.ts +++ b/src/modules/staking/ETH-staking-api/getWbethWrapHistory.ts @@ -1,66 +1,72 @@ // src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethWrapHistory(server: McpServer) { - server.tool( - "BinanceGetWbethWrapHistory", + server.registerTool( + "BinanceGetWbethWrapHistory", + { + description: "Get WBETH Wrap History API allows users to retrieve historical records of WBETH wrap operations, including asset conversion details, exchange rates, and transaction status.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethWrapHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethWrapHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical records of WBETH wrap operations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical records of WBETH wrap operations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical records of WBETH wrap operations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical records of WBETH wrap operations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/index.ts b/src/modules/staking/ETH-staking-api/index.ts index f2641ade..9430f1f2 100644 --- a/src/modules/staking/ETH-staking-api/index.ts +++ b/src/modules/staking/ETH-staking-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-staking/ETH-staking-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceEthStakingAccount } from "./ethStakingAccount.js"; import { registerBinanceGetCurrentEthStakingQuota } from "./getCurrentEthStakingQuota.js"; import { registerBinanceGetEthRedemptionHistory } from "./getEthRedemptionHistory.js"; @@ -13,15 +14,15 @@ import { registerBinanceSubscribeEthStaking } from "./subscribeEthStaking.js"; import { registerBinanceWrapBeth } from "./wrapBeth.js"; export function registerBinanceETHStakingApiTools(server: McpServer) { - registerBinanceEthStakingAccount(server); - registerBinanceGetCurrentEthStakingQuota(server); - registerBinanceGetEthRedemptionHistory(server); - registerBinanceGetEthStakingHistory(server); - registerBinanceGetWbethRateHistory(server); - registerBinanceGetWbethRewardsHistory(server); - registerBinanceGetWbethUnwrapHistory(server); - registerBinanceGetWbethWrapHistory(server); - registerBinanceRedeemEth(server); - registerBinanceSubscribeEthStaking(server); - registerBinanceWrapBeth(server); + registerBinanceEthStakingAccount(server); + registerBinanceGetCurrentEthStakingQuota(server); + registerBinanceGetEthRedemptionHistory(server); + registerBinanceGetEthStakingHistory(server); + registerBinanceGetWbethRateHistory(server); + registerBinanceGetWbethRewardsHistory(server); + registerBinanceGetWbethUnwrapHistory(server); + registerBinanceGetWbethWrapHistory(server); + registerBinanceRedeemEth(server); + registerBinanceSubscribeEthStaking(server); + registerBinanceWrapBeth(server); } diff --git a/src/modules/staking/ETH-staking-api/redeemEth.ts b/src/modules/staking/ETH-staking-api/redeemEth.ts index 20dc7b60..ba81b6fb 100644 --- a/src/modules/staking/ETH-staking-api/redeemEth.ts +++ b/src/modules/staking/ETH-staking-api/redeemEth.ts @@ -1,47 +1,57 @@ // src/tools/binance-staking/ETH-staking-api/redeemEth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemEth(server: McpServer) { - server.tool( - "BinanceRedeemEth", + server.registerTool( + "BinanceRedeemEth", + { + description: "Redeem ETH API allows users to redeem WBETH or BETH for ETH, providing the amount, conversion ratio, and arrival time details.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 8 decimals (mandatory)"), - asset: z.string().optional().default("BETH").describe("Asset type, either WBETH or BETH. Default: BETH"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.redeemEth({ - amount: params.amount, - asset: params.asset, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 8 decimals (mandatory)"), + asset: z + .string() + .optional() + .default("BETH") + .describe("Asset type, either WBETH or BETH. Default: BETH"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.redeemEth({ + amount: params.amount, + asset: params.asset, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully redeemed WBETH or BETH for ETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully redeemed WBETH or BETH for ETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to redeem WBETH or BETH for ETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to redeem WBETH or BETH for ETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/subscribeEthStaking.ts b/src/modules/staking/ETH-staking-api/subscribeEthStaking.ts index b10e1946..ef4108b9 100644 --- a/src/modules/staking/ETH-staking-api/subscribeEthStaking.ts +++ b/src/modules/staking/ETH-staking-api/subscribeEthStaking.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeEthStaking(server: McpServer) { - server.tool( - "BinanceSubscribeEthStaking", + server.registerTool( + "BinanceSubscribeEthStaking", + { + description: "Subscribe ETH Staking API allows users to stake ETH and receive WBETH, providing the staked amount and the conversion ratio for ETH to WBETH.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.subscribeEthStaking({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.subscribeEthStaking({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully staked ETH and receive WBETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully staked ETH and receive WBETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to stake ETH and receive WBETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to stake ETH and receive WBETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/ETH-staking-api/wrapBeth.ts b/src/modules/staking/ETH-staking-api/wrapBeth.ts index c753711a..2d64825f 100644 --- a/src/modules/staking/ETH-staking-api/wrapBeth.ts +++ b/src/modules/staking/ETH-staking-api/wrapBeth.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETHStaking-api/wrapBeth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceWrapBeth(server: McpServer) { - server.tool( - "BinanceWrapBeth", + server.registerTool( + "BinanceWrapBeth", + { + description: "Wrap BETH API allows users to convert BETH into WBETH, providing the wrapped WBETH amount and the exchange rate from BETH to WBETH.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.wrapBeth({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.wrapBeth({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully convert BETH into WBETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully convert BETH into WBETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to convert BETH into WBETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to convert BETH into WBETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/claimBoostRewards.ts b/src/modules/staking/SOL-staking-api/claimBoostRewards.ts index fbb1eaaf..dfb6a7f6 100644 --- a/src/modules/staking/SOL-staking-api/claimBoostRewards.ts +++ b/src/modules/staking/SOL-staking-api/claimBoostRewards.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceClaimBoostRewards(server: McpServer) { - server.tool( - "BinanceClaimBoostRewards", + server.registerTool( + "BinanceClaimBoostRewards", + { + description: "Claim Boost Rewards API allows users to claim their Boost APR airdrop rewards for staking.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.claimBoostRewards({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.claimBoostRewards({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully claim Boost APR airdrop rewards for staking. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully claim Boost APR airdrop rewards for staking. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to claim Boost APR airdrop rewards. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to claim Boost APR airdrop rewards. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getBnsolRateHistory.ts b/src/modules/staking/SOL-staking-api/getBnsolRateHistory.ts index 8d3c5a97..613f8029 100644 --- a/src/modules/staking/SOL-staking-api/getBnsolRateHistory.ts +++ b/src/modules/staking/SOL-staking-api/getBnsolRateHistory.ts @@ -1,66 +1,72 @@ // src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBnsolRateHistory(server: McpServer) { - server.tool( - "registerBinanceGetBnsolRateHistory", + server.registerTool( + "registerBinanceGetBnsolRateHistory", + { + description: " Get BNSOL Rate History API allows users to retrieve the historical data of the BNSOL staking rate, including APR and exchange rates for SOL to BNSOL.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBnsolRateHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBnsolRateHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the historical data of the BNSOL staking rate. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the historical data of the BNSOL staking rate. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the historical data of the BNSOL staking rate. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the historical data of the BNSOL staking rate. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getBnsolRewardsHistory.ts b/src/modules/staking/SOL-staking-api/getBnsolRewardsHistory.ts index 360311b2..a74c3c10 100644 --- a/src/modules/staking/SOL-staking-api/getBnsolRewardsHistory.ts +++ b/src/modules/staking/SOL-staking-api/getBnsolRewardsHistory.ts @@ -1,71 +1,77 @@ // src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBnsolRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetBnsolRewardsHistory", + server.registerTool( + "BinanceGetBnsolRewardsHistory", + { + description: "Get Boost Rewards History API allows users to retrieve their historical boost rewards data for staking, including the amount of rewards, token type (e.g., SOL), and status of the rewards (e.g., CLAIM, DISTRIBUTE).", - { - type: z - .enum(["CLAIM", "DISTRIBUTE"]) - .default("CLAIM") - .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBnsolRewardsHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.type && { type: params.type }) - }); + inputSchema: { + type: z + .enum(["CLAIM", "DISTRIBUTE"]) + .default("CLAIM") + .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBnsolRewardsHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.type && { type: params.type }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical boost rewards data for staking. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical boost rewards data for staking. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical boost rewards data for staking. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical boost rewards data for staking. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getBoostRewardsHistory.ts b/src/modules/staking/SOL-staking-api/getBoostRewardsHistory.ts index 790b2f0e..f0d856f9 100644 --- a/src/modules/staking/SOL-staking-api/getBoostRewardsHistory.ts +++ b/src/modules/staking/SOL-staking-api/getBoostRewardsHistory.ts @@ -1,70 +1,76 @@ // src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBoostRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetBoostRewardsHistory", + server.registerTool( + "BinanceGetBoostRewardsHistory", + { + description: "Get Boost Rewards History API allows users to retrieve their boost rewards history for staking activities. This includes the amount of rewards received, the token type (e.g., SOL), and the status of the rewards (e.g., CLAIM or DISTRIBUTE).", - { - type: z - .enum(["CLAIM", "DISTRIBUTE"]) - .default("CLAIM") - .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBoostRewardsHistory({ - type: params.type, - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + type: z + .enum(["CLAIM", "DISTRIBUTE"]) + .default("CLAIM") + .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBoostRewardsHistory({ + type: params.type, + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved boost rewards history for staking activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved boost rewards history for staking activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve boost rewards history for staking activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve boost rewards history for staking activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getSolRedemptionHistory.ts b/src/modules/staking/SOL-staking-api/getSolRedemptionHistory.ts index 009a340c..678447ab 100644 --- a/src/modules/staking/SOL-staking-api/getSolRedemptionHistory.ts +++ b/src/modules/staking/SOL-staking-api/getSolRedemptionHistory.ts @@ -1,64 +1,70 @@ // src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolRedemptionHistory(server: McpServer) { - server.tool( - "BinanceGetSolRedemptionHistory", + server.registerTool( + "BinanceGetSolRedemptionHistory", + { + description: "Get SOL Redemption History API allows users to retrieve their SOL redemption history, detailing the amount of BNSOL redeemed for SOL and the exchange rate.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolRedemptionHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolRedemptionHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved SOL redemption history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved SOL redemption history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL redemption history. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL redemption history. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getSolStakingHistory.ts b/src/modules/staking/SOL-staking-api/getSolStakingHistory.ts index cb8f4ec9..5e059682 100644 --- a/src/modules/staking/SOL-staking-api/getSolStakingHistory.ts +++ b/src/modules/staking/SOL-staking-api/getSolStakingHistory.ts @@ -1,64 +1,70 @@ // src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolStakingHistory(server: McpServer) { - server.tool( - "BinanceGetSolStakingHistory", + server.registerTool( + "BinanceGetSolStakingHistory", + { + description: "Get SOL Staking History API allows users to retrieve their SOL staking history, including details about the amount of SOL staked, the equivalent BNSOL amount distributed, the exchange rate, and the status of each staking.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolStakingHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolStakingHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved SOL staking history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved SOL staking history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL staking history. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL staking history. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getSolStakingQuotaDetails.ts b/src/modules/staking/SOL-staking-api/getSolStakingQuotaDetails.ts index ce5df6e9..0caf796c 100644 --- a/src/modules/staking/SOL-staking-api/getSolStakingQuotaDetails.ts +++ b/src/modules/staking/SOL-staking-api/getSolStakingQuotaDetails.ts @@ -1,43 +1,49 @@ // src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolStakingQuotaDetails(server: McpServer) { - server.tool( - "getSolStakingQuotaDetails", + server.registerTool( + "getSolStakingQuotaDetails", + { + description: "Get SOL Staking Quota API allows users to retrieve their current SOL staking quota, including information such as the remaining staking and redemption limits, minimum staking and redeem amounts, commission fees, and the status of staking and redemption availability.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolStakingQuotaDetails({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolStakingQuotaDetails({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current SOL staking quota. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current SOL staking quota. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve current SOL staking quota. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve current SOL staking quota. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/getUnclaimedRewards.ts b/src/modules/staking/SOL-staking-api/getUnclaimedRewards.ts index 67bee5c5..ae1c5241 100644 --- a/src/modules/staking/SOL-staking-api/getUnclaimedRewards.ts +++ b/src/modules/staking/SOL-staking-api/getUnclaimedRewards.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetUnclaimedRewards(server: McpServer) { - server.tool( - "BinanceGetUnclaimedRewards", + server.registerTool( + "BinanceGetUnclaimedRewards", + { + description: "Get Unclaimed Rewards API allows users to retrieve information about unclaimed rewards from their SOL staking activities.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getUnclaimedRewards({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getUnclaimedRewards({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved information about unclaimed rewards. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved information about unclaimed rewards. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve information about unclaimed rewards. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve information about unclaimed rewards. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/index.ts b/src/modules/staking/SOL-staking-api/index.ts index cd12159d..1485119d 100644 --- a/src/modules/staking/SOL-staking-api/index.ts +++ b/src/modules/staking/SOL-staking-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-staking/SOL-staking-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceClaimBoostRewards } from "./claimBoostRewards.js"; import { registerBinanceGetBnsolRateHistory } from "./getBnsolRateHistory.js"; import { registerBinanceGetBnsolRewardsHistory } from "./getBnsolRewardsHistory.js"; @@ -13,15 +14,15 @@ import { registerBinanceSolStakingAccount } from "./solStakingAccount.js"; import { registerBinanceSubscribeSolStaking } from "./subscribeSolStaking.js"; export function registerBinanceSOLStakingApiTools(server: McpServer) { - registerBinanceClaimBoostRewards(server); - registerBinanceGetBnsolRateHistory(server); - registerBinanceGetBnsolRewardsHistory(server); - registerBinanceGetBoostRewardsHistory(server); - registerBinanceGetSolRedemptionHistory(server); - registerBinanceGetSolStakingHistory(server); - registerBinanceGetSolStakingQuotaDetails(server); - registerBinanceGetUnclaimedRewards(server); - registerBinanceRedeemSol(server); - registerBinanceSolStakingAccount(server); - registerBinanceSubscribeSolStaking(server); + registerBinanceClaimBoostRewards(server); + registerBinanceGetBnsolRateHistory(server); + registerBinanceGetBnsolRewardsHistory(server); + registerBinanceGetBoostRewardsHistory(server); + registerBinanceGetSolRedemptionHistory(server); + registerBinanceGetSolStakingHistory(server); + registerBinanceGetSolStakingQuotaDetails(server); + registerBinanceGetUnclaimedRewards(server); + registerBinanceRedeemSol(server); + registerBinanceSolStakingAccount(server); + registerBinanceSubscribeSolStaking(server); } diff --git a/src/modules/staking/SOL-staking-api/redeemSol.ts b/src/modules/staking/SOL-staking-api/redeemSol.ts index fa98b3b1..49b98bb8 100644 --- a/src/modules/staking/SOL-staking-api/redeemSol.ts +++ b/src/modules/staking/SOL-staking-api/redeemSol.ts @@ -1,47 +1,57 @@ // src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemSol(server: McpServer) { - server.tool( - "registerBinanceRedeemSol", + server.registerTool( + "registerBinanceRedeemSol", + { + description: " Redeem SOL API allows users to redeem BNSOL and receive SOL in exchange. It enables the conversion of BNSOL tokens into SOL based on the specified amount", - { - amount: z.number().min(0).max(99999999).describe("Amount in BNSOL, limit to 8 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.redeemSol({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z + .number() + .min(0) + .max(99999999) + .describe("Amount in BNSOL, limit to 8 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.redeemSol({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully redeem BNSOL and receive SOL in exchange. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully redeem BNSOL and receive SOL in exchange. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to redeem BNSOL and receive SOL in exchange. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to redeem BNSOL and receive SOL in exchange. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/solStakingAccount.ts b/src/modules/staking/SOL-staking-api/solStakingAccount.ts index 17506fb6..54f9a305 100644 --- a/src/modules/staking/SOL-staking-api/solStakingAccount.ts +++ b/src/modules/staking/SOL-staking-api/solStakingAccount.ts @@ -1,43 +1,49 @@ // src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSolStakingAccount(server: McpServer) { - server.tool( - "registerBinanceSolStakingAccount", + server.registerTool( + "registerBinanceSolStakingAccount", + { + description: "SOL Staking Account API allows users to view their SOL staking account details, including their current BNSOL holdings, equivalent SOL balance, and the profit in SOL over the past 30 days.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.solStakingAccount({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.solStakingAccount({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve SOL staking account details: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve SOL staking account details: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL staking account details. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL staking account details. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/SOL-staking-api/subscribeSolStaking.ts b/src/modules/staking/SOL-staking-api/subscribeSolStaking.ts index 65fded66..853b3a46 100644 --- a/src/modules/staking/SOL-staking-api/subscribeSolStaking.ts +++ b/src/modules/staking/SOL-staking-api/subscribeSolStaking.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeSolStaking(server: McpServer) { - server.tool( - "BinanceSubscribeSolStaking", + server.registerTool( + "BinanceSubscribeSolStaking", + { + description: "Subscribe SOL Staking API allows users to stake SOL and receive BNSOL in return. This endpoint requires specifying the amount of SOL to stake, and the response includes the equivalent BNSOL amount and exchange rate for SOL to BNSOL.", - { - amount: z.number().min(0).describe("Amount in SOL (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.subscribeSolStaking({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in SOL (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.subscribeSolStaking({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully stake SOL and receive BNSOL in return: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully stake SOL and receive BNSOL in return: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to stake SOL. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to stake SOL. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/staking/index.ts b/src/modules/staking/index.ts index e95ed99e..d44b79ef 100644 --- a/src/modules/staking/index.ts +++ b/src/modules/staking/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-staking/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceETHStakingApiTools } from "./ETH-staking-api/index.js"; import { registerBinanceSOLStakingApiTools } from "./SOL-staking-api/index.js"; export function registerBinanceStakingTools(server: McpServer) { - registerBinanceETHStakingApiTools(server); - registerBinanceSOLStakingApiTools(server); + registerBinanceETHStakingApiTools(server); + registerBinanceSOLStakingApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/sub-account/index.ts b/src/modules/sub-account/index.ts index f1fc6d63..3ebd3f25 100644 --- a/src/modules/sub-account/index.ts +++ b/src/modules/sub-account/index.ts @@ -1,7 +1,8 @@ // src/modules/sub-account/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSubAccountTools } from "../../tools/binance-sub-account/index.js"; export function registerSubAccount(server: McpServer) { - registerBinanceSubAccountTools(server); + registerBinanceSubAccountTools(server); } diff --git a/src/modules/vip-loan/index.ts b/src/modules/vip-loan/index.ts index 60395c22..a15c905e 100644 --- a/src/modules/vip-loan/index.ts +++ b/src/modules/vip-loan/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-vip-loan/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceVipLoanMarketApiTools } from "./market-api/index.js"; import { registerBinanceVipLoanTradeApiTools } from "./trade-api/index.js"; import { registerBinanceVipLoanUserInformationApiTools } from "./userInformation-api/index.js"; export function registerBinanceVipLoanTools(server: McpServer) { - registerBinanceVipLoanMarketApiTools(server); - registerBinanceVipLoanTradeApiTools(server); - registerBinanceVipLoanUserInformationApiTools(server); + registerBinanceVipLoanMarketApiTools(server); + registerBinanceVipLoanTradeApiTools(server); + registerBinanceVipLoanUserInformationApiTools(server); } // Alias for binance.ts compatibility diff --git a/src/modules/vip-loan/market-api/getBorrowInterestRate.ts b/src/modules/vip-loan/market-api/getBorrowInterestRate.ts index 51888e73..44d6f45d 100644 --- a/src/modules/vip-loan/market-api/getBorrowInterestRate.ts +++ b/src/modules/vip-loan/market-api/getBorrowInterestRate.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBorrowInterestRate(server: McpServer) { - server.tool( - "BinanceGetBorrowInterestRate", + server.registerTool( + "BinanceGetBorrowInterestRate", + { + description: "Retrieves the interest rates for borrowing assets. It provides both daily and yearly interest rates for multiple assets (e.g., BUSD, BTC). You can specify the assets by using a comma-separated list.", - { - loanCoin: z.string().min(1).describe("Max 10 assets, multiple split by ','"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getBorrowInterestRate({ - loanCoin: params.loanCoin, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().min(1).describe("Max 10 assets, multiple split by ','"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getBorrowInterestRate({ + loanCoin: params.loanCoin, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the interest rates for borrowing assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the interest rates for borrowing assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the interest rates for borrowing assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the interest rates for borrowing assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/market-api/getCollateralAssetData.ts b/src/modules/vip-loan/market-api/getCollateralAssetData.ts index 5f9c7a34..2c87c84c 100644 --- a/src/modules/vip-loan/market-api/getCollateralAssetData.ts +++ b/src/modules/vip-loan/market-api/getCollateralAssetData.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetCollateralAssetData(server: McpServer) { - server.tool( - "BinanceGetCollateralAssetData", + server.registerTool( + "BinanceGetCollateralAssetData", + { + description: "Retrieves information about collateral assets, including collateral ratios and range values for different tiers of collateral. The ratios are used to determine the collateral requirement for various levels of borrowing.", - { - collateralCoin: z.string().optional().describe("Optional: Coin used as collateral"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getCollateralAssetData({ - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + collateralCoin: z.string().optional().describe("Optional: Coin used as collateral"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getCollateralAssetData({ + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved information about collateral assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved information about collateral assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve information about collateral assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve information about collateral assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/market-api/getLoanableAssetsData.ts b/src/modules/vip-loan/market-api/getLoanableAssetsData.ts index 5c256508..8c448656 100644 --- a/src/modules/vip-loan/market-api/getLoanableAssetsData.ts +++ b/src/modules/vip-loan/market-api/getLoanableAssetsData.ts @@ -1,49 +1,63 @@ // src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetLoanableAssetsData(server: McpServer) { - server.tool( - "BinanceGetLoanableAssetsData", + server.registerTool( + "BinanceGetLoanableAssetsData", + { + description: "Retrieves interest rates and borrowing limits for loanable assets. The borrow limit is expressed in USD. You can request information for specific assets or leave it empty to query all available assets.", - { - loanCoin: z.string().optional().describe("Optional: Coin for the loan"), - vipLevel: z.number().int().optional().describe("Optional: User's VIP level (default is user's vip level)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getLoanableAssetsData({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.vipLevel && { vipLevel: params.vipLevel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Optional: Coin for the loan"), + vipLevel: z + .number() + .int() + .optional() + .describe("Optional: User's VIP level (default is user's vip level)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getLoanableAssetsData({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.vipLevel && { vipLevel: params.vipLevel }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved interest rates and borrowing limits for loanable assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved interest rates and borrowing limits for loanable assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve interest rates and borrowing limits for loanable assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve interest rates and borrowing limits for loanable assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/market-api/index.ts b/src/modules/vip-loan/market-api/index.ts index 3e0ee81a..5ee3c97f 100644 --- a/src/modules/vip-loan/market-api/index.ts +++ b/src/modules/vip-loan/market-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetBorrowInterestRate } from "./getBorrowInterestRate.js"; -import { registerBinanceGetLoanableAssetsData } from "./getLoanableAssetsData.js"; import { registerBinanceGetCollateralAssetData } from "./getCollateralAssetData.js"; +import { registerBinanceGetLoanableAssetsData } from "./getLoanableAssetsData.js"; export function registerBinanceVipLoanMarketApiTools(server: McpServer) { - registerBinanceGetBorrowInterestRate(server); - registerBinanceGetCollateralAssetData(server); - registerBinanceGetLoanableAssetsData(server); + registerBinanceGetBorrowInterestRate(server); + registerBinanceGetCollateralAssetData(server); + registerBinanceGetLoanableAssetsData(server); } diff --git a/src/modules/vip-loan/trade-api/index.ts b/src/modules/vip-loan/trade-api/index.ts index 7395b3ff..95c9cb6c 100644 --- a/src/modules/vip-loan/trade-api/index.ts +++ b/src/modules/vip-loan/trade-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceVipLoanBorrow } from "./vipLoanBorrow.js"; import { registerBinanceVipLoanRenew } from "./vipLoanRenew.js"; import { registerBinanceVipLoanRepay } from "./vipLoanRepay.js"; -import { registerBinanceVipLoanBorrow } from "./vipLoanBorrow.js"; export function registerBinanceVipLoanTradeApiTools(server: McpServer) { - registerBinanceVipLoanRenew(server); - registerBinanceVipLoanRepay(server); - registerBinanceVipLoanBorrow(server); + registerBinanceVipLoanRenew(server); + registerBinanceVipLoanRepay(server); + registerBinanceVipLoanBorrow(server); } diff --git a/src/modules/vip-loan/trade-api/vipLoanBorrow.ts b/src/modules/vip-loan/trade-api/vipLoanBorrow.ts index 2dc82b5f..e69a71e2 100644 --- a/src/modules/vip-loan/trade-api/vipLoanBorrow.ts +++ b/src/modules/vip-loan/trade-api/vipLoanBorrow.ts @@ -1,59 +1,78 @@ // src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanBorrow(server: McpServer) { - server.tool( - "BinanceVipLoanBorrow", + server.registerTool( + "BinanceVipLoanBorrow", + { + description: "Allow users (master account only) to apply for a loan by pledging collateral. Users specify the coin they want to borrow, the amount, and the collateral details.", - { - loanAccountId: z.number().int().describe("Loan account ID"), - loanCoin: z.string().min(1).describe("Loan coin (e.g., BTC, ETH)"), - loanAmount: z.number().describe("Loan amount as decimal"), - collateralAccountId: z.string().min(1).describe("Collateral account IDs, separated by commas"), - collateralCoin: z.string().min(1).describe("Collateral coins, separated by commas"), - isFlexibleRate: z.boolean().describe("TRUE: flexible rate, FALSE: fixed rate. Default: TRUE"), - loanTerm: z.number().int().optional().describe("Loan term (only required if fixed rate, e.g., 30/60 days)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanBorrow({ - loanAccountId: params.loanAccountId, - loanCoin: params.loanCoin, - loanAmount: params.loanAmount, - collateralAccountId: params.collateralAccountId, - collateralCoin: params.collateralCoin, - isFlexibleRate: params.isFlexibleRate, - ...(params.loanTerm !== undefined && { loanTerm: params.loanTerm }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanAccountId: z.number().int().describe("Loan account ID"), + loanCoin: z.string().min(1).describe("Loan coin (e.g., BTC, ETH)"), + loanAmount: z.number().describe("Loan amount as decimal"), + collateralAccountId: z + .string() + .min(1) + .describe("Collateral account IDs, separated by commas"), + collateralCoin: z.string().min(1).describe("Collateral coins, separated by commas"), + isFlexibleRate: z + .boolean() + .describe("TRUE: flexible rate, FALSE: fixed rate. Default: TRUE"), + loanTerm: z + .number() + .int() + .optional() + .describe("Loan term (only required if fixed rate, e.g., 30/60 days)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanBorrow({ + loanAccountId: params.loanAccountId, + loanCoin: params.loanCoin, + loanAmount: params.loanAmount, + collateralAccountId: params.collateralAccountId, + collateralCoin: params.collateralCoin, + isFlexibleRate: params.isFlexibleRate, + ...(params.loanTerm !== undefined && { loanTerm: params.loanTerm }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully apply for a loan by pledging collateral. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully apply for a loan by pledging collateral. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to apply for a loan by pledging collateral. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to apply for a loan by pledging collateral. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/trade-api/vipLoanRenew.ts b/src/modules/vip-loan/trade-api/vipLoanRenew.ts index 50e7491c..a05a1d43 100644 --- a/src/modules/vip-loan/trade-api/vipLoanRenew.ts +++ b/src/modules/vip-loan/trade-api/vipLoanRenew.ts @@ -1,46 +1,58 @@ // src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanRenew(server: McpServer) { - server.tool( - "BinanceVipLoanRenew", + server.registerTool( + "BinanceVipLoanRenew", + { + description: "Allow VIP users to renew an existing VIP loan for a specified term, either 30 or 60 days.", - { - orderId: z.number().int().describe("The order ID for the loan request"), - loanTerm: z.union([z.literal(30), z.literal(60)]).describe("Loan term in days, either 30 or 60"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanRenew({ - orderId: params.orderId, - loanTerm: params.loanTerm, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + orderId: z.number().int().describe("The order ID for the loan request"), + loanTerm: z + .union([z.literal(30), z.literal(60)]) + .describe("Loan term in days, either 30 or 60"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanRenew({ + orderId: params.orderId, + loanTerm: params.loanTerm, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully renew an existing VIP loan. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully renew an existing VIP loan. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to renew an existing VIP loan. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to renew an existing VIP loan. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/trade-api/vipLoanRepay.ts b/src/modules/vip-loan/trade-api/vipLoanRepay.ts index e6389ef0..3b8c2e71 100644 --- a/src/modules/vip-loan/trade-api/vipLoanRepay.ts +++ b/src/modules/vip-loan/trade-api/vipLoanRepay.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanRepay(server: McpServer) { - server.tool( - "BinanceVipLoanRepay", + server.registerTool( + "BinanceVipLoanRepay", + { + description: "Allow VIP users to repay a specified amount of their active loan, partially or fully. It updates the remaining principal and interest, and provides the repayment status.", - { - orderId: z.number().int().describe("Order ID of the loan request"), - amount: z.number().describe("Amount to be processed (decimal allowed)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanRepay({ - orderId: params.orderId, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().describe("Order ID of the loan request"), + amount: z.number().describe("Amount to be processed (decimal allowed)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanRepay({ + orderId: params.orderId, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully repay the active loan. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully repay the active loan. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to repay the active loan. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to repay the active loan. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts b/src/modules/vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts index 841d583e..c7cea037 100644 --- a/src/modules/vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts +++ b/src/modules/vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts @@ -1,51 +1,61 @@ // src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCheckVIPLoanCollateralAccount(server: McpServer) { - server.tool( - "BinanceCheckVIPLoanCollateralAccount", + server.registerTool( + "BinanceCheckVIPLoanCollateralAccount", + { + description: "Allow users to check their collateral accounts and the coins held as collateral. If the logged-in account is a loan account, it will return all associated collateral accounts. If it's a collateral account, it returns details of the current account only.", - { - orderId: z.number().int().optional().describe("Optional order ID"), - collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.checkVIPLoanCollateralAccount({ - ...(params.orderId !== undefined && { orderId: params.orderId }), - ...(params.collateralAccountId !== undefined && { - collateralAccountId: params.collateralAccountId - }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().optional().describe("Optional order ID"), + collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.checkVIPLoanCollateralAccount({ + ...(params.orderId !== undefined && { orderId: params.orderId }), + ...(params.collateralAccountId !== undefined && { + collateralAccountId: params.collateralAccountId, + }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved collateral accounts and the coins held as collateral. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved collateral accounts and the coins held as collateral. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve collateral accounts and the coins held as collateral. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve collateral accounts and the coins held as collateral. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts b/src/modules/vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts index 70c69c6f..f1edc4b2 100644 --- a/src/modules/vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts +++ b/src/modules/vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts @@ -1,59 +1,81 @@ // src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetVIPLoanOngoingOrders(server: McpServer) { - server.tool( - "BinanceGetVIPLoanOngoingOrders", + server.registerTool( + "BinanceGetVIPLoanOngoingOrders", + { + description: "Allows VIP users to retrieve a list of their current active loan orders. Users can filter results by loan coin, collateral coin, order ID, or collateral account ID.", - { - orderId: z.number().int().optional().describe("Optional order ID"), - collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), - loanCoin: z.string().optional().describe("Optional loan coin"), - collateralCoin: z.string().optional().describe("Optional collateral coin"), - current: z.number().int().min(1).max(1000).optional().describe("Current page, start from 1, max 1000"), - limit: z.number().int().min(1).max(100).optional().describe("Results per page, default 10, max 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getVIPLoanOngoingOrders({ - ...(params.orderId !== undefined && { orderId: params.orderId }), - ...(params.collateralAccountId !== undefined && { - collateralAccountId: params.collateralAccountId - }), - ...(params.loanCoin !== undefined && { loanCoin: params.loanCoin }), - ...(params.collateralCoin !== undefined && { collateralCoin: params.collateralCoin }), - ...(params.current !== undefined && { current: params.current }), - ...(params.limit !== undefined && { limit: params.limit }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().optional().describe("Optional order ID"), + collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), + loanCoin: z.string().optional().describe("Optional loan coin"), + collateralCoin: z.string().optional().describe("Optional collateral coin"), + current: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Current page, start from 1, max 1000"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Results per page, default 10, max 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getVIPLoanOngoingOrders({ + ...(params.orderId !== undefined && { orderId: params.orderId }), + ...(params.collateralAccountId !== undefined && { + collateralAccountId: params.collateralAccountId, + }), + ...(params.loanCoin !== undefined && { loanCoin: params.loanCoin }), + ...(params.collateralCoin !== undefined && { collateralCoin: params.collateralCoin }), + ...(params.current !== undefined && { current: params.current }), + ...(params.limit !== undefined && { limit: params.limit }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved list of their current active loan orders. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved list of their current active loan orders. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve list of their current active loan orders. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve list of their current active loan orders. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/vip-loan/userInformation-api/index.ts b/src/modules/vip-loan/userInformation-api/index.ts index 58bad6e4..fcffe103 100644 --- a/src/modules/vip-loan/userInformation-api/index.ts +++ b/src/modules/vip-loan/userInformation-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/userInformation-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCheckVIPLoanCollateralAccount } from "./checkVIPLoanCollateralAccount.js"; import { registerBinanceGetVIPLoanOngoingOrders } from "./getVIPLoanOngoingOrders.js"; import { registerBinanceQueryApplicationStatus } from "./queryApplicationStatus.js"; export function registerBinanceVipLoanUserInformationApiTools(server: McpServer) { - registerBinanceCheckVIPLoanCollateralAccount(server); - registerBinanceGetVIPLoanOngoingOrders(server); - registerBinanceQueryApplicationStatus(server); + registerBinanceCheckVIPLoanCollateralAccount(server); + registerBinanceGetVIPLoanOngoingOrders(server); + registerBinanceQueryApplicationStatus(server); } diff --git a/src/modules/vip-loan/userInformation-api/queryApplicationStatus.ts b/src/modules/vip-loan/userInformation-api/queryApplicationStatus.ts index 7d5e5a05..8d7d1b96 100644 --- a/src/modules/vip-loan/userInformation-api/queryApplicationStatus.ts +++ b/src/modules/vip-loan/userInformation-api/queryApplicationStatus.ts @@ -1,55 +1,65 @@ // src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceQueryApplicationStatus(server: McpServer) { - server.tool( - "BinanceQueryApplicationStatus", + server.registerTool( + "BinanceQueryApplicationStatus", + { + description: "Allows VIP users to check the status of their loan applications. It returns a list of loan requests with details such as loan coin, amount, term, collateral details, and current application status", - { - current: z - .number() - .int() - .min(1) - .max(1000) - .optional() - .describe("Currently querying page. Start from 1, default 1, max 1000"), - limit: z.number().int().min(1).max(100).optional().describe("Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.queryApplicationStatus({ - ...(params.current !== undefined && { current: params.current }), - ...(params.limit !== undefined && { limit: params.limit }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + current: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Currently querying page. Start from 1, default 1, max 1000"), + limit: z.number().int().min(1).max(100).optional().describe("Default: 10, Max: 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.queryApplicationStatus({ + ...(params.current !== undefined && { current: params.current }), + ...(params.limit !== undefined && { limit: params.limit }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved status of their loan applications. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved status of their loan applications. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve status of their loan applications.. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve status of their loan applications.. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/modules/wallet/account-api/accountApiTradingStatus.ts b/src/modules/wallet/account-api/accountApiTradingStatus.ts index d5ed7e7b..99e08066 100644 --- a/src/modules/wallet/account-api/accountApiTradingStatus.ts +++ b/src/modules/wallet/account-api/accountApiTradingStatus.ts @@ -1,40 +1,48 @@ // src/tools/binance-wallet/account-api/accountApiTradingStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountApiTradingStatus(server: McpServer) { - server.tool( - "BinanceWalletAccountApiTradingStatus", - "Get account API trading status.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountApiTradingStatus(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountApiTradingStatus", + { + description: "Get account API trading status.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountApiTradingStatus(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved account API trading status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account API trading status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account API trading status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve account API trading status: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/accountInfo.ts b/src/modules/wallet/account-api/accountInfo.ts index 4b426dc4..74e27c16 100644 --- a/src/modules/wallet/account-api/accountInfo.ts +++ b/src/modules/wallet/account-api/accountInfo.ts @@ -1,40 +1,48 @@ // src/tools/binance-wallet/account-api/accountInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountInfo(server: McpServer) { - server.tool( - "BinanceWalletAccountInfo", - "Get Binance Wallet account information.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountInfo(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountInfo", + { + description: "Get Binance Wallet account information.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountInfo(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved wallet account information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved wallet account information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve wallet account information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve wallet account information: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/accountStatus.ts b/src/modules/wallet/account-api/accountStatus.ts index e5efdcec..e76fb3b2 100644 --- a/src/modules/wallet/account-api/accountStatus.ts +++ b/src/modules/wallet/account-api/accountStatus.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/accountStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountStatus(server: McpServer) { - server.tool( - "BinanceWalletAccountStatus", - "Get Binance Wallet account status.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountStatus(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountStatus", + { + description: "Get Binance Wallet account status.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountStatus(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved wallet account status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved wallet account status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve wallet account status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve wallet account status: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/dailyAccountSnapshot.ts b/src/modules/wallet/account-api/dailyAccountSnapshot.ts index 8bfde6f8..388a6906 100644 --- a/src/modules/wallet/account-api/dailyAccountSnapshot.ts +++ b/src/modules/wallet/account-api/dailyAccountSnapshot.ts @@ -1,47 +1,52 @@ // src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDailyAccountSnapshot(server: McpServer) { - server.tool( - "BinanceWalletDailyAccountSnapshot", - "Get daily account snapshot.", - { - type: z.string().describe("The account type (e.g., SPOT, MARGIN, FUTURES)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 7, max 30"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, startTime, endTime, limit, recvWindow }) => { - try { - const params: any = { type }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dailyAccountSnapshot(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDailyAccountSnapshot", + { + description: "Get daily account snapshot.", + inputSchema: { + type: z.string().describe("The account type (e.g., SPOT, MARGIN, FUTURES)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 7, max 30"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, startTime, endTime, limit, recvWindow }) => { + try { + const params: any = { type }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dailyAccountSnapshot(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved daily account snapshot for ${type}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved daily account snapshot for ${type}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve daily account snapshot: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve daily account snapshot: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/disableFastWithdrawSwitch.ts b/src/modules/wallet/account-api/disableFastWithdrawSwitch.ts index 5e0e8106..46b33792 100644 --- a/src/modules/wallet/account-api/disableFastWithdrawSwitch.ts +++ b/src/modules/wallet/account-api/disableFastWithdrawSwitch.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDisableFastWithdrawSwitch(server: McpServer) { - server.tool( - "BinanceWalletDisableFastWithdrawSwitch", - "Disable fast withdraw switch.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.disableFastWithdrawSwitch(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDisableFastWithdrawSwitch", + { + description: "Disable fast withdraw switch.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.disableFastWithdrawSwitch(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Disabled fast withdraw switch. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Disabled fast withdraw switch. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to disable fast withdraw switch: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to disable fast withdraw switch: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/enableFastWithdrawSwitch.ts b/src/modules/wallet/account-api/enableFastWithdrawSwitch.ts index d6679332..b4d54e4b 100644 --- a/src/modules/wallet/account-api/enableFastWithdrawSwitch.ts +++ b/src/modules/wallet/account-api/enableFastWithdrawSwitch.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletEnableFastWithdrawSwitch(server: McpServer) { - server.tool( - "BinanceWalletEnableFastWithdrawSwitch", - "Enable fast withdraw switch.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.enableFastWithdrawSwitch(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletEnableFastWithdrawSwitch", + { + description: "Enable fast withdraw switch.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.enableFastWithdrawSwitch(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Enabled fast withdraw switch. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Enabled fast withdraw switch. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to enable fast withdraw switch: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to enable fast withdraw switch: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/getApiKeyPermission.ts b/src/modules/wallet/account-api/getApiKeyPermission.ts index 773e8175..cab47335 100644 --- a/src/modules/wallet/account-api/getApiKeyPermission.ts +++ b/src/modules/wallet/account-api/getApiKeyPermission.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/getApiKeyPermission.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetApiKeyPermission(server: McpServer) { - server.tool( - "BinanceWalletGetApiKeyPermission", - "Get API key permission.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getApiKeyPermission(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetApiKeyPermission", + { + description: "Get API key permission.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getApiKeyPermission(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved API key permission. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved API key permission. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve API key permission: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve API key permission: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/account-api/index.ts b/src/modules/wallet/account-api/index.ts index 0b8cfdf0..d454e39c 100644 --- a/src/modules/wallet/account-api/index.ts +++ b/src/modules/wallet/account-api/index.ts @@ -1,20 +1,20 @@ // src/tools/binance-wallet/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletDailyAccountSnapshot } from "./dailyAccountSnapshot.js"; -import { registerBinanceWalletGetApiKeyPermission } from "./getApiKeyPermission.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceWalletAccountApiTradingStatus } from "./accountApiTradingStatus.js"; import { registerBinanceWalletAccountInfo } from "./accountInfo.js"; import { registerBinanceWalletAccountStatus } from "./accountStatus.js"; -import { registerBinanceWalletAccountApiTradingStatus } from "./accountApiTradingStatus.js"; -import { registerBinanceWalletEnableFastWithdrawSwitch } from "./enableFastWithdrawSwitch.js"; +import { registerBinanceWalletDailyAccountSnapshot } from "./dailyAccountSnapshot.js"; import { registerBinanceWalletDisableFastWithdrawSwitch } from "./disableFastWithdrawSwitch.js"; +import { registerBinanceWalletEnableFastWithdrawSwitch } from "./enableFastWithdrawSwitch.js"; +import { registerBinanceWalletGetApiKeyPermission } from "./getApiKeyPermission.js"; export function registerBinanceWalletAccountApiTools(server: McpServer) { - registerBinanceWalletDailyAccountSnapshot(server); - registerBinanceWalletGetApiKeyPermission(server); - registerBinanceWalletAccountInfo(server); - registerBinanceWalletAccountStatus(server); - registerBinanceWalletAccountApiTradingStatus(server); - registerBinanceWalletEnableFastWithdrawSwitch(server); - registerBinanceWalletDisableFastWithdrawSwitch(server); - -} \ No newline at end of file + registerBinanceWalletDailyAccountSnapshot(server); + registerBinanceWalletGetApiKeyPermission(server); + registerBinanceWalletAccountInfo(server); + registerBinanceWalletAccountStatus(server); + registerBinanceWalletAccountApiTradingStatus(server); + registerBinanceWalletEnableFastWithdrawSwitch(server); + registerBinanceWalletDisableFastWithdrawSwitch(server); +} diff --git a/src/modules/wallet/asset-api/assetDetail.ts b/src/modules/wallet/asset-api/assetDetail.ts index 8eabf38b..c4f5a55b 100644 --- a/src/modules/wallet/asset-api/assetDetail.ts +++ b/src/modules/wallet/asset-api/assetDetail.ts @@ -1,42 +1,45 @@ // src/tools/binance-wallet/asset-api/assetDetail.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAssetDetail(server: McpServer) { - server.tool( - "BinanceWalletAssetDetail", - "Get asset details.", - { - asset: z.string().optional().describe("Asset symbol"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.assetDetail(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAssetDetail", + { + description: "Get asset details.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.assetDetail(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved asset details. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset details. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset details: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve asset details: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/assetDividendRecord.ts b/src/modules/wallet/asset-api/assetDividendRecord.ts index c24cff7d..29dbba85 100644 --- a/src/modules/wallet/asset-api/assetDividendRecord.ts +++ b/src/modules/wallet/asset-api/assetDividendRecord.ts @@ -1,48 +1,53 @@ // src/tools/binance-wallet/asset-api/assetDividendRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAssetDividendRecord(server: McpServer) { - server.tool( - "BinanceWalletAssetDividendRecord", - "Get asset dividend record.", - { - asset: z.string().optional().describe("Asset symbol"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 20, max 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, startTime, endTime, limit, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.assetDividendRecord(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAssetDividendRecord", + { + description: "Get asset dividend record.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 20, max 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, startTime, endTime, limit, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.assetDividendRecord(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved asset dividend record. Total records: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset dividend record. Total records: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset dividend record: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve asset dividend record: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/dustTransfer.ts b/src/modules/wallet/asset-api/dustTransfer.ts index 74d7b520..0be0bdb5 100644 --- a/src/modules/wallet/asset-api/dustTransfer.ts +++ b/src/modules/wallet/asset-api/dustTransfer.ts @@ -1,42 +1,44 @@ - // src/tools/binance-wallet/asset-api/dustTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDustTransfer(server: McpServer) { - server.tool( - "BinanceWalletDustTransfer", - "Convert dust assets to BNB.", - { - asset: z.array(z.string()).describe("Array of asset symbols to convert"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: any = { asset }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dustTransfer(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDustTransfer", + { + description: "Convert dust assets to BNB.", + inputSchema: { + asset: z.array(z.string()).describe("Array of asset symbols to convert"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: any = { asset }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dustTransfer(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Dust transfer completed. Total BNB received: ${data.totalServiceCharge || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Dust transfer completed. Total BNB received: ${data.totalServiceCharge || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to process dust transfer: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to process dust transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/dustlog.ts b/src/modules/wallet/asset-api/dustlog.ts index 9ad92947..c1ccd2d6 100644 --- a/src/modules/wallet/asset-api/dustlog.ts +++ b/src/modules/wallet/asset-api/dustlog.ts @@ -1,44 +1,47 @@ // src/tools/binance-wallet/asset-api/dustlog.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDustlog(server: McpServer) { - server.tool( - "BinanceWalletDustlog", - "Get dust log (history of dust transfers).", - { - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ startTime, endTime, recvWindow }) => { - try { - const params: any = {}; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dustlog(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDustlog", + { + description: "Get dust log (history of dust transfers).", + inputSchema: { + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ startTime, endTime, recvWindow }) => { + try { + const params: any = {}; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dustlog(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved dust log. Total transfers: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved dust log. Total transfers: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve dust log: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve dust log: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/fundingWallet.ts b/src/modules/wallet/asset-api/fundingWallet.ts index 0a08c73f..226a7bc6 100644 --- a/src/modules/wallet/asset-api/fundingWallet.ts +++ b/src/modules/wallet/asset-api/fundingWallet.ts @@ -1,44 +1,49 @@ // src/tools/binance-wallet/asset-api/fundingWallet.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFundingWallet(server: McpServer) { - server.tool( - "BinanceWalletFundingWallet", - "Get funding wallet balance.", - { - asset: z.string().optional().describe("Asset symbol"), - needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, needBtcValuation, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.fundingWallet(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletFundingWallet", + { + description: "Get funding wallet balance.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, needBtcValuation, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.fundingWallet(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved funding wallet balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved funding wallet balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve funding wallet balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve funding wallet balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts b/src/modules/wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts index 8c5a3ef1..f969e0c5 100644 --- a/src/modules/wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts +++ b/src/modules/wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts @@ -1,40 +1,47 @@ // src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server: McpServer) { - server.tool( - "BinanceWalletGetAssetsThatCanBeConvertedIntoBnb", - "Get assets that can be converted to BNB.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getAssetsThatCanBeConvertedIntoBnb(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetAssetsThatCanBeConvertedIntoBnb", + { + description: "Get assets that can be converted to BNB.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getAssetsThatCanBeConvertedIntoBnb( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved assets that can be converted to BNB. Total: ${data.details?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved assets that can be converted to BNB. Total: ${data.details?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve convertible assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve convertible assets: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts b/src/modules/wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts index d8317c6b..4953b9e6 100644 --- a/src/modules/wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts +++ b/src/modules/wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts @@ -1,49 +1,56 @@ // src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server: McpServer) { - server.tool( - "BinanceWalletGetCloudMiningPaymentAndRefundHistory", - "Get cloud mining payment and refund history.", - { - startTime: z.number().describe("Start time in milliseconds"), - endTime: z.number().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number"), - pageSize: z.number().optional().describe("Page size"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ startTime, endTime, page, pageSize, recvWindow }) => { - try { - const params: any = { - startTime, - endTime - }; - if (page !== undefined) params.page = page; - if (pageSize !== undefined) params.pageSize = pageSize; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getCloudMiningPaymentAndRefundHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetCloudMiningPaymentAndRefundHistory", + { + description: "Get cloud mining payment and refund history.", + inputSchema: { + startTime: z.number().describe("Start time in milliseconds"), + endTime: z.number().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number"), + pageSize: z.number().optional().describe("Page size"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ startTime, endTime, page, pageSize, recvWindow }) => { + try { + const params: any = { + startTime, + endTime, + }; + if (page !== undefined) params.page = page; + if (pageSize !== undefined) params.pageSize = pageSize; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getCloudMiningPaymentAndRefundHistory( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved cloud mining payment and refund history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved cloud mining payment and refund history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve cloud mining history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve cloud mining history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/getOpenSymbolList.ts b/src/modules/wallet/asset-api/getOpenSymbolList.ts index dee5dbcf..ce26b78e 100644 --- a/src/modules/wallet/asset-api/getOpenSymbolList.ts +++ b/src/modules/wallet/asset-api/getOpenSymbolList.ts @@ -1,35 +1,33 @@ // src/tools/binance-wallet/asset-api/getOpenSymbolList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetOpenSymbolList(server: McpServer) { - server.tool( - "BinanceWalletGetOpenSymbolList", - "Get open symbol list.", - {}, - async () => { - try { - const response = await walletClient.restAPI.getOpenSymbolList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetOpenSymbolList", + { description: "Get open symbol list." }, + async () => { + try { + const response = await (walletClient as any).restAPI.getOpenSymbolList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved open symbol list. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open symbol list. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open symbol list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open symbol list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/index.ts b/src/modules/wallet/asset-api/index.ts index c3d59031..d06e8cd3 100644 --- a/src/modules/wallet/asset-api/index.ts +++ b/src/modules/wallet/asset-api/index.ts @@ -1,35 +1,36 @@ // src/tools/binance-wallet/asset-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletUserAsset } from "./userAsset.js"; -import { registerBinanceWalletFundingWallet } from "./fundingWallet.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAssetDetail } from "./assetDetail.js"; -import { registerBinanceWalletTradeFee } from "./tradeFee.js"; -import { registerBinanceWalletUserUniversalTransfer } from "./userUniversalTransfer.js"; -import { registerBinanceWalletQueryUserUniversalTransferHistory } from "./queryUserUniversalTransferHistory.js"; -import { registerBinanceWalletDustTransfer } from "./dustTransfer.js"; -import { registerBinanceWalletDustlog } from "./dustlog.js"; import { registerBinanceWalletAssetDividendRecord } from "./assetDividendRecord.js"; +import { registerBinanceWalletDustlog } from "./dustlog.js"; +import { registerBinanceWalletDustTransfer } from "./dustTransfer.js"; +import { registerBinanceWalletFundingWallet } from "./fundingWallet.js"; import { registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb } from "./getAssetsThatCanBeConvertedIntoBnb.js"; -import { registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest } from "./toggleBnbBurnOnSpotTradeAndMarginInterest.js"; import { registerBinanceWalletGetCloudMiningPaymentAndRefundHistory } from "./getCloudMiningPaymentAndRefundHistory.js"; -import { registerBinanceWalletQueryUserDelegationHistory } from "./queryUserDelegationHistory.js"; import { registerBinanceWalletGetOpenSymbolList } from "./getOpenSymbolList.js"; +import { registerBinanceWalletQueryUserDelegationHistory } from "./queryUserDelegationHistory.js"; +import { registerBinanceWalletQueryUserUniversalTransferHistory } from "./queryUserUniversalTransferHistory.js"; import { registerBinanceWalletQueryUserWalletBalance } from "./queryUserWalletBalance.js"; +import { registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest } from "./toggleBnbBurnOnSpotTradeAndMarginInterest.js"; +import { registerBinanceWalletTradeFee } from "./tradeFee.js"; +import { registerBinanceWalletUserAsset } from "./userAsset.js"; +import { registerBinanceWalletUserUniversalTransfer } from "./userUniversalTransfer.js"; export function registerBinanceWalletAssetApiTools(server: McpServer) { - registerBinanceWalletUserAsset(server); - registerBinanceWalletFundingWallet(server); - registerBinanceWalletAssetDetail(server); - registerBinanceWalletTradeFee(server); - registerBinanceWalletUserUniversalTransfer(server); - registerBinanceWalletQueryUserUniversalTransferHistory(server); - registerBinanceWalletDustTransfer(server); - registerBinanceWalletDustlog(server); - registerBinanceWalletAssetDividendRecord(server); - registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server); - registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server); - registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server); - registerBinanceWalletQueryUserDelegationHistory(server); - registerBinanceWalletGetOpenSymbolList(server); - registerBinanceWalletQueryUserWalletBalance(server); -} \ No newline at end of file + registerBinanceWalletUserAsset(server); + registerBinanceWalletFundingWallet(server); + registerBinanceWalletAssetDetail(server); + registerBinanceWalletTradeFee(server); + registerBinanceWalletUserUniversalTransfer(server); + registerBinanceWalletQueryUserUniversalTransferHistory(server); + registerBinanceWalletDustTransfer(server); + registerBinanceWalletDustlog(server); + registerBinanceWalletAssetDividendRecord(server); + registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server); + registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server); + registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server); + registerBinanceWalletQueryUserDelegationHistory(server); + registerBinanceWalletGetOpenSymbolList(server); + registerBinanceWalletQueryUserWalletBalance(server); +} diff --git a/src/modules/wallet/asset-api/queryUserDelegationHistory.ts b/src/modules/wallet/asset-api/queryUserDelegationHistory.ts index 02075a79..b2e75a0f 100644 --- a/src/modules/wallet/asset-api/queryUserDelegationHistory.ts +++ b/src/modules/wallet/asset-api/queryUserDelegationHistory.ts @@ -1,51 +1,56 @@ // src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserDelegationHistory(server: McpServer) { - server.tool( - "BinanceWalletQueryUserDelegationHistory", - "Query user delegation history.", - { - email: z.string().describe("Email address"), - startTime: z.number().describe("Start time in milliseconds"), - endTime: z.number().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number"), - limit: z.number().optional().describe("Results per page"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, startTime, endTime, page, limit, recvWindow }) => { - try { - const params: any = { - email, - startTime, - endTime - }; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserDelegationHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserDelegationHistory", + { + description: "Query user delegation history.", + inputSchema: { + email: z.string().describe("Email address"), + startTime: z.number().describe("Start time in milliseconds"), + endTime: z.number().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number"), + limit: z.number().optional().describe("Results per page"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, startTime, endTime, page, limit, recvWindow }) => { + try { + const params: any = { + email, + startTime, + endTime, + }; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserDelegationHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user delegation history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user delegation history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user delegation history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve user delegation history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/queryUserUniversalTransferHistory.ts b/src/modules/wallet/asset-api/queryUserUniversalTransferHistory.ts index 59e3fca7..edfa2703 100644 --- a/src/modules/wallet/asset-api/queryUserUniversalTransferHistory.ts +++ b/src/modules/wallet/asset-api/queryUserUniversalTransferHistory.ts @@ -1,53 +1,63 @@ // src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserUniversalTransferHistory(server: McpServer) { - server.tool( - "BinanceWalletQueryUserUniversalTransferHistory", - "Query universal transfer history.", - { - type: z.string().describe("Transfer type"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - size: z.number().optional().describe("Page size"), - fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, startTime, endTime, current, size, fromSymbol, toSymbol, recvWindow }) => { - try { - const params: any = { type }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (size !== undefined) params.size = size; - if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; - if (toSymbol !== undefined) params.toSymbol = toSymbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserUniversalTransferHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserUniversalTransferHistory", + { + description: "Query universal transfer history.", + inputSchema: { + type: z.string().describe("Transfer type"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + size: z.number().optional().describe("Page size"), + fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, startTime, endTime, current, size, fromSymbol, toSymbol, recvWindow }) => { + try { + const params: any = { type }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (size !== undefined) params.size = size; + if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; + if (toSymbol !== undefined) params.toSymbol = toSymbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserUniversalTransferHistory( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved universal transfer history. Total: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved universal transfer history. Total: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve universal transfer history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve universal transfer history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/queryUserWalletBalance.ts b/src/modules/wallet/asset-api/queryUserWalletBalance.ts index b386a6d5..2a1520fb 100644 --- a/src/modules/wallet/asset-api/queryUserWalletBalance.ts +++ b/src/modules/wallet/asset-api/queryUserWalletBalance.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserWalletBalance(server: McpServer) { - server.tool( - "BinanceWalletQueryUserWalletBalance", - "Query user wallet balance.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserWalletBalance(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserWalletBalance", + { + description: "Query user wallet balance.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserWalletBalance(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user wallet balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user wallet balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user wallet balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve user wallet balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts b/src/modules/wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts index bf05c09b..688fcb5b 100644 --- a/src/modules/wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts +++ b/src/modules/wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts @@ -1,44 +1,49 @@ // src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server: McpServer) { - server.tool( - "BinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest", - "Toggle BNB burn on spot trade and margin interest.", - { - spotBNBBurn: z.string().optional().describe("'true' or 'false' for spot trade"), - interestBNBBurn: z.string().optional().describe("'true' or 'false' for margin interest"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ spotBNBBurn, interestBNBBurn, recvWindow }) => { - try { - const params: any = {}; - if (spotBNBBurn !== undefined) params.spotBNBBurn = spotBNBBurn; - if (interestBNBBurn !== undefined) params.interestBNBBurn = interestBNBBurn; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.toggleBnbBurnOnSpotTradeAndMarginInterest(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest", + { + description: "Toggle BNB burn on spot trade and margin interest.", + inputSchema: { + spotBNBBurn: z.string().optional().describe("'true' or 'false' for spot trade"), + interestBNBBurn: z.string().optional().describe("'true' or 'false' for margin interest"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ spotBNBBurn, interestBNBBurn, recvWindow }) => { + try { + const params: any = {}; + if (spotBNBBurn !== undefined) params.spotBNBBurn = spotBNBBurn; + if (interestBNBBurn !== undefined) params.interestBNBBurn = interestBNBBurn; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await ( + walletClient as any + ).restAPI.toggleBnbBurnOnSpotTradeAndMarginInterest(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `BNB burn settings updated. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `BNB burn settings updated. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to update BNB burn settings: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to update BNB burn settings: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/tradeFee.ts b/src/modules/wallet/asset-api/tradeFee.ts index e1a613a0..6861de41 100644 --- a/src/modules/wallet/asset-api/tradeFee.ts +++ b/src/modules/wallet/asset-api/tradeFee.ts @@ -1,42 +1,47 @@ // src/tools/binance-wallet/asset-api/tradeFee.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletTradeFee(server: McpServer) { - server.tool( - "BinanceWalletTradeFee", - "Get trade fee.", - { - symbol: z.string().optional().describe("Trading pair symbol"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, recvWindow }) => { - try { - const params: any = {}; - if (symbol !== undefined) params.symbol = symbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.tradeFee(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletTradeFee", + { + description: "Get trade fee.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, recvWindow }) => { + try { + const params: any = {}; + if (symbol !== undefined) params.symbol = symbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.tradeFee(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved trade fee information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved trade fee information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve trade fee information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve trade fee information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/userAsset.ts b/src/modules/wallet/asset-api/userAsset.ts index f0d373e6..b9122d07 100644 --- a/src/modules/wallet/asset-api/userAsset.ts +++ b/src/modules/wallet/asset-api/userAsset.ts @@ -1,42 +1,45 @@ // src/tools/binance-wallet/asset-api/userAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletUserAsset(server: McpServer) { - server.tool( - "BinanceWalletUserAsset", - "Get user assets.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation") - }, - async ({ recvWindow, needBtcValuation }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; - - const response = await walletClient.restAPI.userAsset(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletUserAsset", + { + description: "Get user assets.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), + }, + }, + async ({ recvWindow, needBtcValuation }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; + + const response = await (walletClient as any).restAPI.userAsset(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user assets. Number of assets: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user assets. Number of assets: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve user assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/asset-api/userUniversalTransfer.ts b/src/modules/wallet/asset-api/userUniversalTransfer.ts index 3f9cf173..0f9527e2 100644 --- a/src/modules/wallet/asset-api/userUniversalTransfer.ts +++ b/src/modules/wallet/asset-api/userUniversalTransfer.ts @@ -1,52 +1,56 @@ - // src/tools/binance-wallet/asset-api/userUniversalTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletUserUniversalTransfer(server: McpServer) { - server.tool( - "BinanceWalletUserUniversalTransfer", - "Make universal transfer between different accounts.", - { - type: z.string().describe("Transfer type"), - asset: z.string().describe("Asset symbol"), - amount: z.number().describe("Transfer amount"), - fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, asset, amount, fromSymbol, toSymbol, recvWindow }) => { - try { - const params: any = { - type, - asset, - amount - }; - if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; - if (toSymbol !== undefined) params.toSymbol = toSymbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.userUniversalTransfer(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletUserUniversalTransfer", + { + description: "Make universal transfer between different accounts.", + inputSchema: { + type: z.string().describe("Transfer type"), + asset: z.string().describe("Asset symbol"), + amount: z.number().describe("Transfer amount"), + fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, asset, amount, fromSymbol, toSymbol, recvWindow }) => { + try { + const params: any = { + type, + asset, + amount, + }; + if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; + if (toSymbol !== undefined) params.toSymbol = toSymbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.userUniversalTransfer(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Universal transfer completed. Transfer ID: ${data.tranId}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Universal transfer completed. Transfer ID: ${data.tranId}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to process universal transfer: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to process universal transfer: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/allCoinsInformation.ts b/src/modules/wallet/capital-api/allCoinsInformation.ts index 1dc48aad..5d998209 100644 --- a/src/modules/wallet/capital-api/allCoinsInformation.ts +++ b/src/modules/wallet/capital-api/allCoinsInformation.ts @@ -1,40 +1,43 @@ // src/tools/binance-wallet/capital-api/allCoinsInformation.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAllCoinsInformation(server: McpServer) { - server.tool( - "BinanceWalletAllCoinsInformation", - "Get information for all coins.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.allCoinsInformation(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAllCoinsInformation", + { + description: "Get information for all coins.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.allCoinsInformation(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved information for all coins. Total coins: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved information for all coins. Total coins: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve coin information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve coin information: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/depositAddress.ts b/src/modules/wallet/capital-api/depositAddress.ts index cbcc2d66..0ecb0015 100644 --- a/src/modules/wallet/capital-api/depositAddress.ts +++ b/src/modules/wallet/capital-api/depositAddress.ts @@ -1,43 +1,46 @@ // src/tools/binance-wallet/capital-api/depositAddress.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositAddress(server: McpServer) { - server.tool( - "BinanceWalletDepositAddress", - "Get deposit address for a specific coin.", - { - coin: z.string().describe("Coin symbol"), - network: z.string().optional().describe("Network"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, network, recvWindow }) => { - try { - const params: any = { coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.depositAddress(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDepositAddress", + { + description: "Get deposit address for a specific coin.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + network: z.string().optional().describe("Network"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, recvWindow }) => { + try { + const params: any = { coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositAddress(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit address for ${coin}. Address: ${data.address}${data.tag ? `, Tag: ${data.tag}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit address for ${coin}. Address: ${data.address}${data.tag ? `, Tag: ${data.tag}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit address: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit address: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/depositHistory.ts b/src/modules/wallet/capital-api/depositHistory.ts index 20c3ed33..67729320 100644 --- a/src/modules/wallet/capital-api/depositHistory.ts +++ b/src/modules/wallet/capital-api/depositHistory.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/capital-api/depositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositHistory(server: McpServer) { - server.tool( - "BinanceWalletDepositHistory", - "Get deposit history.", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Deposit status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Pagination offset"), - limit: z.number().optional().describe("Number of records to return"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; + server.registerTool( + "BinanceWalletDepositHistory", + { + description: "Get deposit history.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Deposit status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Pagination offset"), + limit: z.number().optional().describe("Number of records to return"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositHistory(params); + const data = await response.data(); - const response = await walletClient.restAPI.depositHistory(params); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved deposit history. Total deposits: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit history. Total deposits: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/fetchDepositAddressListWithNetwork.ts b/src/modules/wallet/capital-api/fetchDepositAddressListWithNetwork.ts index a9b87324..684fa6c5 100644 --- a/src/modules/wallet/capital-api/fetchDepositAddressListWithNetwork.ts +++ b/src/modules/wallet/capital-api/fetchDepositAddressListWithNetwork.ts @@ -1,43 +1,50 @@ // src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFetchDepositAddressListWithNetwork(server: McpServer) { - server.tool( - "BinanceWalletFetchDepositAddressListWithNetwork", - "Fetch deposit address with network.", - { - coin: z.string().describe("Coin symbol"), - network: z.string().optional().describe("Network"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, network, recvWindow }) => { - try { - const params: any = { coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.fetchDepositAddressListWithNetwork(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletFetchDepositAddressListWithNetwork", + { + description: "Fetch deposit address with network.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + network: z.string().optional().describe("Network"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, recvWindow }) => { + try { + const params: any = { coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.fetchDepositAddressListWithNetwork( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit addresses for ${coin}. Total addresses: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit addresses for ${coin}. Total addresses: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit addresses: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve deposit addresses: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/fetchWithdrawAddressList.ts b/src/modules/wallet/capital-api/fetchWithdrawAddressList.ts index 1aa56a22..10f899eb 100644 --- a/src/modules/wallet/capital-api/fetchWithdrawAddressList.ts +++ b/src/modules/wallet/capital-api/fetchWithdrawAddressList.ts @@ -1,37 +1,35 @@ // src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFetchWithdrawAddressList(server: McpServer) { - server.tool( - "BinanceWalletFetchWithdrawAddressList", - "Fetch withdraw address list.", - { - }, - async () => { - try { - - const response = await walletClient.restAPI.fetchWithdrawAddressList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletFetchWithdrawAddressList", + { description: "Fetch withdraw address list." }, + async () => { + try { + const response = await (walletClient as any).restAPI.fetchWithdrawAddressList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw address list. Total addresses: ${data || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw address list. Total addresses: ${data || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw address list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve withdraw address list: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/index.ts b/src/modules/wallet/capital-api/index.ts index be8c1ac1..f1086cd9 100644 --- a/src/modules/wallet/capital-api/index.ts +++ b/src/modules/wallet/capital-api/index.ts @@ -1,21 +1,22 @@ // src/tools/binance-wallet/capital-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAllCoinsInformation } from "./allCoinsInformation.js"; import { registerBinanceWalletDepositAddress } from "./depositAddress.js"; import { registerBinanceWalletDepositHistory } from "./depositHistory.js"; -import { registerBinanceWalletWithdrawHistory } from "./withdrawHistory.js"; -import { registerBinanceWalletWithdraw } from "./withdraw.js"; import { registerBinanceWalletFetchDepositAddressListWithNetwork } from "./fetchDepositAddressListWithNetwork.js"; import { registerBinanceWalletFetchWithdrawAddressList } from "./fetchWithdrawAddressList.js"; import { registerBinanceWalletOneClickArrivalDepositApply } from "./oneClickArrivalDepositApply.js"; +import { registerBinanceWalletWithdraw } from "./withdraw.js"; +import { registerBinanceWalletWithdrawHistory } from "./withdrawHistory.js"; export function registerBinanceWalletCapitalApiTools(server: McpServer) { - registerBinanceWalletAllCoinsInformation(server); - registerBinanceWalletDepositAddress(server); - registerBinanceWalletDepositHistory(server); - registerBinanceWalletWithdrawHistory(server); - registerBinanceWalletWithdraw(server); - registerBinanceWalletFetchDepositAddressListWithNetwork(server); - registerBinanceWalletFetchWithdrawAddressList(server); - registerBinanceWalletOneClickArrivalDepositApply(server); -} \ No newline at end of file + registerBinanceWalletAllCoinsInformation(server); + registerBinanceWalletDepositAddress(server); + registerBinanceWalletDepositHistory(server); + registerBinanceWalletWithdrawHistory(server); + registerBinanceWalletWithdraw(server); + registerBinanceWalletFetchDepositAddressListWithNetwork(server); + registerBinanceWalletFetchWithdrawAddressList(server); + registerBinanceWalletOneClickArrivalDepositApply(server); +} diff --git a/src/modules/wallet/capital-api/oneClickArrivalDepositApply.ts b/src/modules/wallet/capital-api/oneClickArrivalDepositApply.ts index 8ecc17ed..794acc72 100644 --- a/src/modules/wallet/capital-api/oneClickArrivalDepositApply.ts +++ b/src/modules/wallet/capital-api/oneClickArrivalDepositApply.ts @@ -1,42 +1,50 @@ // src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletOneClickArrivalDepositApply(server: McpServer) { - server.tool( - "BinanceWalletOneClickArrivalDepositApply", - "Apply for one-click arrival deposit.", - { - subAccountId: z.string().optional().describe("Sub-account ID"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, recvWindow }) => { - try { - const params: any = {}; - if (subAccountId !== undefined) params.subAccountId = subAccountId; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.oneClickArrivalDepositApply(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletOneClickArrivalDepositApply", + { + description: "Apply for one-click arrival deposit.", + inputSchema: { + subAccountId: z.string().optional().describe("Sub-account ID"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, recvWindow }) => { + try { + const params: any = {}; + if (subAccountId !== undefined) params.subAccountId = subAccountId; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.oneClickArrivalDepositApply(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Applied for one-click arrival deposit. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Applied for one-click arrival deposit. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to apply for one-click arrival deposit: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to apply for one-click arrival deposit: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/withdraw.ts b/src/modules/wallet/capital-api/withdraw.ts index 50e4c1a6..c759c25a 100644 --- a/src/modules/wallet/capital-api/withdraw.ts +++ b/src/modules/wallet/capital-api/withdraw.ts @@ -1,59 +1,73 @@ // src/tools/binance-wallet/capital-api/withdraw.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdraw(server: McpServer) { - server.tool( - "BinanceWalletWithdraw", - "Submit a withdraw request.", - { - coin: z.string().describe("Coin symbol"), - address: z.string().describe("Withdrawal address"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().optional().describe("Client order id"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier (tag/memo)"), - name: z.string().optional().describe("Address name"), - walletType: z.number().optional().describe("Wallet type"), - transactionFeeFlag: z.boolean().optional().describe("Pay fee with BNB"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, address, amount, withdrawOrderId, network, addressTag, name, walletType, transactionFeeFlag, recvWindow }) => { - try { - const params: any = { - coin, - address, - amount - }; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (walletType !== undefined) params.walletType = walletType; - if (transactionFeeFlag !== undefined) params.transactionFeeFlag = transactionFeeFlag; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdraw(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdraw", + { + description: "Submit a withdraw request.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + address: z.string().describe("Withdrawal address"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().optional().describe("Client order id"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier (tag/memo)"), + name: z.string().optional().describe("Address name"), + walletType: z.number().optional().describe("Wallet type"), + transactionFeeFlag: z.boolean().optional().describe("Pay fee with BNB"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + coin, + address, + amount, + withdrawOrderId, + network, + addressTag, + name, + walletType, + transactionFeeFlag, + recvWindow, + }) => { + try { + const params: any = { + coin, + address, + amount, + }; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (walletType !== undefined) params.walletType = walletType; + if (transactionFeeFlag !== undefined) params.transactionFeeFlag = transactionFeeFlag; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdraw(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Withdraw request submitted. Withdrawal ID: ${data.id}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Withdraw request submitted. Withdrawal ID: ${data.id}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit withdraw request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to submit withdraw request: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/capital-api/withdrawHistory.ts b/src/modules/wallet/capital-api/withdrawHistory.ts index f846925c..e9c7cec7 100644 --- a/src/modules/wallet/capital-api/withdrawHistory.ts +++ b/src/modules/wallet/capital-api/withdrawHistory.ts @@ -1,54 +1,57 @@ // src/tools/binance-wallet/capital-api/withdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistory(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistory", - "Get withdraw history.", - { - coin: z.string().optional().describe("Coin symbol"), - withdrawOrderId: z.string().optional().describe("Withdraw order ID"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Pagination offset"), - limit: z.number().optional().describe("Number of records to return"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistory", + { + description: "Get withdraw history.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + withdrawOrderId: z.string().optional().describe("Withdraw order ID"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Pagination offset"), + limit: z.number().optional().describe("Number of records to return"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history. Total withdrawals: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history. Total withdrawals: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/index.ts b/src/modules/wallet/index.ts index 42703575..86747df4 100644 --- a/src/modules/wallet/index.ts +++ b/src/modules/wallet/index.ts @@ -1,27 +1,28 @@ // src/tools/binance-wallet/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAccountApiTools } from "./account-api/index.js"; -import { registerBinanceWalletOthersApiTools } from "./others-api/index.js"; -import { registerBinanceWalletTravelRuleApiTools } from "./travel-rule-api/index.js"; import { registerBinanceWalletAssetApiTools } from "./asset-api/index.js"; import { registerBinanceWalletCapitalApiTools } from "./capital-api/index.js"; +import { registerBinanceWalletOthersApiTools } from "./others-api/index.js"; +import { registerBinanceWalletTravelRuleApiTools } from "./travel-rule-api/index.js"; export function registerBinanceWalletTools(server: McpServer) { - // Account API tools - registerBinanceWalletAccountApiTools(server); - - // Others API tools - registerBinanceWalletOthersApiTools(server); - - // Travel Rule API tools - registerBinanceWalletTravelRuleApiTools(server); - - // Asset API tools - registerBinanceWalletAssetApiTools(server); - - // Capital API tools - registerBinanceWalletCapitalApiTools(server); + // Account API tools + registerBinanceWalletAccountApiTools(server); + + // Others API tools + registerBinanceWalletOthersApiTools(server); + + // Travel Rule API tools + registerBinanceWalletTravelRuleApiTools(server); + + // Asset API tools + registerBinanceWalletAssetApiTools(server); + + // Capital API tools + registerBinanceWalletCapitalApiTools(server); } // Alias for binance.ts compatibility -export { registerBinanceWalletTools as registerWallet }; \ No newline at end of file +export { registerBinanceWalletTools as registerWallet }; diff --git a/src/modules/wallet/others-api/getSymbolsDelistScheduleForSpot.ts b/src/modules/wallet/others-api/getSymbolsDelistScheduleForSpot.ts index f1c4f0f6..3ef67fe7 100644 --- a/src/modules/wallet/others-api/getSymbolsDelistScheduleForSpot.ts +++ b/src/modules/wallet/others-api/getSymbolsDelistScheduleForSpot.ts @@ -1,34 +1,33 @@ // src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetSymbolsDelistScheduleForSpot(server: McpServer) { - server.tool( - "BinanceWalletGetSymbolsDelistScheduleForSpot", - "Get delist schedule for spot symbols.", - {}, - async () => { - try { - const response = await walletClient.restAPI.getSymbolsDelistScheduleForSpot(); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetSymbolsDelistScheduleForSpot", + { description: "Get delist schedule for spot symbols." }, + async () => { + try { + const response = await (walletClient as any).restAPI.getSymbolsDelistScheduleForSpot(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved delist schedule for spot symbols. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved delist schedule for spot symbols. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve delist schedule: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve delist schedule: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/others-api/index.ts b/src/modules/wallet/others-api/index.ts index d0ca0559..e1f899e4 100644 --- a/src/modules/wallet/others-api/index.ts +++ b/src/modules/wallet/others-api/index.ts @@ -1,10 +1,10 @@ //src/tools/binance-wallet/others-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletSystemStatus } from "./systemStatus.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletGetSymbolsDelistScheduleForSpot } from "./getSymbolsDelistScheduleForSpot.js"; +import { registerBinanceWalletSystemStatus } from "./systemStatus.js"; export function registerBinanceWalletOthersApiTools(server: McpServer) { - registerBinanceWalletSystemStatus(server); - registerBinanceWalletGetSymbolsDelistScheduleForSpot(server); - -} \ No newline at end of file + registerBinanceWalletSystemStatus(server); + registerBinanceWalletGetSymbolsDelistScheduleForSpot(server); +} diff --git a/src/modules/wallet/others-api/systemStatus.ts b/src/modules/wallet/others-api/systemStatus.ts index 57e4133e..f218dcdd 100644 --- a/src/modules/wallet/others-api/systemStatus.ts +++ b/src/modules/wallet/others-api/systemStatus.ts @@ -1,34 +1,33 @@ // src/tools/binance-wallet/others-api/systemStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSystemStatus(server: McpServer) { - server.tool( - "BinanceWalletSystemStatus", - "Get Binance Wallet system status.", - {}, - async () => { - try { - const response = await walletClient.restAPI.systemStatus(); - const data = await response.data(); + server.registerTool( + "BinanceWalletSystemStatus", + { description: "Get Binance Wallet system status." }, + async () => { + try { + const response = await (walletClient as any).restAPI.systemStatus(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved system status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved system status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve system status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve system status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/brokerWithdraw.ts b/src/modules/wallet/travel-rule-api/brokerWithdraw.ts index 08be01e6..e2a34782 100644 --- a/src/modules/wallet/travel-rule-api/brokerWithdraw.ts +++ b/src/modules/wallet/travel-rule-api/brokerWithdraw.ts @@ -1,63 +1,81 @@ // src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletBrokerWithdraw(server: McpServer) { - server.tool( - "BinanceWalletBrokerWithdraw", - "Initiate broker withdrawal with travel rule compliance.", - { - subAccountId: z.string().describe("Sub-account ID"), - address: z.string().describe("Withdrawal address"), - coin: z.string().describe("Coin symbol"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().describe("Client order id"), - questionnaire: z.string().describe("Travel rule questionnaire"), - originatorPii: z.string().describe("Originator PII information"), - signature: z.string().describe("Signature"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier"), - name: z.string().optional().describe("Address name"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, address, coin, amount, withdrawOrderId, questionnaire, originatorPii, signature, network, addressTag, name, recvWindow }) => { - try { - const params: any = { - subAccountId, - address, - coin, - amount, - withdrawOrderId, - questionnaire, - originatorPii, - signature - }; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.brokerWithdraw(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletBrokerWithdraw", + { + description: "Initiate broker withdrawal with travel rule compliance.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + address: z.string().describe("Withdrawal address"), + coin: z.string().describe("Coin symbol"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().describe("Client order id"), + questionnaire: z.string().describe("Travel rule questionnaire"), + originatorPii: z.string().describe("Originator PII information"), + signature: z.string().describe("Signature"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier"), + name: z.string().optional().describe("Address name"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + subAccountId, + address, + coin, + amount, + withdrawOrderId, + questionnaire, + originatorPii, + signature, + network, + addressTag, + name, + recvWindow, + }) => { + try { + const params: any = { + subAccountId, + address, + coin, + amount, + withdrawOrderId, + questionnaire, + originatorPii, + signature, + }; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.brokerWithdraw(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Broker withdraw request submitted. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Broker withdraw request submitted. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit broker withdraw request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit broker withdraw request: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/depositHistoryTravelRule.ts b/src/modules/wallet/travel-rule-api/depositHistoryTravelRule.ts index e86c7efa..4ef383c4 100644 --- a/src/modules/wallet/travel-rule-api/depositHistoryTravelRule.ts +++ b/src/modules/wallet/travel-rule-api/depositHistoryTravelRule.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositHistoryTravelRule(server: McpServer) { - server.tool( - "BinanceWalletDepositHistoryTravelRule", - "Get deposit history for travel rule.", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Deposit status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.depositHistoryTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDepositHistoryTravelRule", + { + description: "Get deposit history for travel rule.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Deposit status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositHistoryTravelRule(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit history for travel rule. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit history for travel rule. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/index.ts b/src/modules/wallet/travel-rule-api/index.ts index 5cafccd8..f475165d 100644 --- a/src/modules/wallet/travel-rule-api/index.ts +++ b/src/modules/wallet/travel-rule-api/index.ts @@ -1,22 +1,22 @@ //src/tools/binance-wallet/travel-rule-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletBrokerWithdraw } from "./brokerWithdraw.js"; +import { registerBinanceWalletDepositHistoryTravelRule } from "./depositHistoryTravelRule.js"; import { registerBinanceWalletOnboardedVaspList } from "./onboardedVaspList.js"; import { registerBinanceWalletSubmitDepositQuestionnaire } from "./submitDepositQuestionnaire.js"; +import { registerBinanceWalletSubmitDepositQuestionnaireTravelRule } from "./submitDepositQuestionnaireTravelRule.js"; import { registerBinanceWalletWithdrawHistoryV1 } from "./withdrawHistoryV1.js"; -import { registerBinanceWalletDepositHistoryTravelRule } from "./depositHistoryTravelRule.js"; import { registerBinanceWalletWithdrawHistoryV2 } from "./withdrawHistoryV2.js"; import { registerBinanceWalletWithdrawTravelRule } from "./withdrawTravelRule.js"; -import { registerBinanceWalletSubmitDepositQuestionnaireTravelRule } from "./submitDepositQuestionnaireTravelRule.js"; export function registerBinanceWalletTravelRuleApiTools(server: McpServer) { - registerBinanceWalletBrokerWithdraw(server); - registerBinanceWalletOnboardedVaspList(server); - registerBinanceWalletSubmitDepositQuestionnaire(server); - registerBinanceWalletWithdrawHistoryV1(server); - registerBinanceWalletDepositHistoryTravelRule(server); - registerBinanceWalletWithdrawHistoryV2(server); - registerBinanceWalletWithdrawTravelRule(server); - registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server); - -} \ No newline at end of file + registerBinanceWalletBrokerWithdraw(server); + registerBinanceWalletOnboardedVaspList(server); + registerBinanceWalletSubmitDepositQuestionnaire(server); + registerBinanceWalletWithdrawHistoryV1(server); + registerBinanceWalletDepositHistoryTravelRule(server); + registerBinanceWalletWithdrawHistoryV2(server); + registerBinanceWalletWithdrawTravelRule(server); + registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server); +} diff --git a/src/modules/wallet/travel-rule-api/onboardedVaspList.ts b/src/modules/wallet/travel-rule-api/onboardedVaspList.ts index d78089c6..8b063cf5 100644 --- a/src/modules/wallet/travel-rule-api/onboardedVaspList.ts +++ b/src/modules/wallet/travel-rule-api/onboardedVaspList.ts @@ -1,35 +1,35 @@ // src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletOnboardedVaspList(server: McpServer) { - server.tool( - "BinanceWalletOnboardedVaspList", - "Get list of onboarded VASPs (Virtual Asset Service Providers).", - {}, - async () => { - try { - const response = await walletClient.restAPI.onboardedVaspList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletOnboardedVaspList", + { description: "Get list of onboarded VASPs (Virtual Asset Service Providers)." }, + async () => { + try { + const response = await (walletClient as any).restAPI.onboardedVaspList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved onboarded VASP list. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved onboarded VASP list. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve onboarded VASP list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve onboarded VASP list: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/submitDepositQuestionnaire.ts b/src/modules/wallet/travel-rule-api/submitDepositQuestionnaire.ts index 37ef2dc6..350be6f0 100644 --- a/src/modules/wallet/travel-rule-api/submitDepositQuestionnaire.ts +++ b/src/modules/wallet/travel-rule-api/submitDepositQuestionnaire.ts @@ -1,51 +1,56 @@ // src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSubmitDepositQuestionnaire(server: McpServer) { - server.tool( - "BinanceWalletSubmitDepositQuestionnaire", - "Submit deposit questionnaire for broker deposit.", - { - subAccountId: z.string().describe("Sub-account ID"), - depositId: z.string().describe("Deposit ID"), - questionnaire: z.string().describe("Travel rule questionnaire"), - beneficiaryPii: z.string().describe("Beneficiary PII information"), - signature: z.string().describe("Signature"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, depositId, questionnaire, beneficiaryPii, signature, recvWindow }) => { - try { - const params: any = { - subAccountId, - depositId, - questionnaire, - beneficiaryPii, - signature - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.submitDepositQuestionnaire(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletSubmitDepositQuestionnaire", + { + description: "Submit deposit questionnaire for broker deposit.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + depositId: z.string().describe("Deposit ID"), + questionnaire: z.string().describe("Travel rule questionnaire"), + beneficiaryPii: z.string().describe("Beneficiary PII information"), + signature: z.string().describe("Signature"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, depositId, questionnaire, beneficiaryPii, signature, recvWindow }) => { + try { + const params: any = { + subAccountId, + depositId, + questionnaire, + beneficiaryPii, + signature, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.submitDepositQuestionnaire(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Submitted deposit questionnaire for broker deposit. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Submitted deposit questionnaire for broker deposit. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts b/src/modules/wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts index 4d2f4f9e..95aadcf7 100644 --- a/src/modules/wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts +++ b/src/modules/wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts @@ -1,45 +1,52 @@ // src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server: McpServer) { - server.tool( - "BinanceWalletSubmitDepositQuestionnaireTravelRule", - "Submit deposit questionnaire for travel rule.", - { - tranId: z.number().describe("Transaction ID"), - questionnaire: z.string().describe("Travel rule questionnaire"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ tranId, questionnaire, recvWindow }) => { - try { - const params: any = { - tranId, - questionnaire - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.submitDepositQuestionnaireTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletSubmitDepositQuestionnaireTravelRule", + { + description: "Submit deposit questionnaire for travel rule.", + inputSchema: { + tranId: z.number().describe("Transaction ID"), + questionnaire: z.string().describe("Travel rule questionnaire"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ tranId, questionnaire, recvWindow }) => { + try { + const params: any = { + tranId, + questionnaire, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.submitDepositQuestionnaireTravelRule( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Submitted deposit questionnaire for travel rule. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Submitted deposit questionnaire for travel rule. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/withdrawHistoryV1.ts b/src/modules/wallet/travel-rule-api/withdrawHistoryV1.ts index 4cf980f9..9cdee180 100644 --- a/src/modules/wallet/travel-rule-api/withdrawHistoryV1.ts +++ b/src/modules/wallet/travel-rule-api/withdrawHistoryV1.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistoryV1(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistoryV1", - "Get withdraw history (v1).", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistoryV1(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistoryV1", + { + description: "Get withdraw history (v1).", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistoryV1(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history v1. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history v1. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/withdrawHistoryV2.ts b/src/modules/wallet/travel-rule-api/withdrawHistoryV2.ts index 2b20d3a2..596e4d97 100644 --- a/src/modules/wallet/travel-rule-api/withdrawHistoryV2.ts +++ b/src/modules/wallet/travel-rule-api/withdrawHistoryV2.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistoryV2(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistoryV2", - "Get withdraw history (v2).", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistoryV2(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistoryV2", + { + description: "Get withdraw history (v2).", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistoryV2(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history v2. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history v2. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/modules/wallet/travel-rule-api/withdrawTravelRule.ts b/src/modules/wallet/travel-rule-api/withdrawTravelRule.ts index 5d7bd8bf..e0c08765 100644 --- a/src/modules/wallet/travel-rule-api/withdrawTravelRule.ts +++ b/src/modules/wallet/travel-rule-api/withdrawTravelRule.ts @@ -1,57 +1,75 @@ // src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawTravelRule(server: McpServer) { - server.tool( - "BinanceWalletWithdrawTravelRule", - "Withdraw with travel rule compliance.", - { - coin: z.string().describe("Coin symbol"), - address: z.string().describe("Withdrawal address"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().optional().describe("Client order id"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier"), - name: z.string().optional().describe("Address name"), - questionnaire: z.string().describe("Travel rule questionnaire"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, address, amount, withdrawOrderId, network, addressTag, name, questionnaire, recvWindow }) => { - try { - const params: any = { - coin, - address, - amount, - questionnaire - }; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawTravelRule", + { + description: "Withdraw with travel rule compliance.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + address: z.string().describe("Withdrawal address"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().optional().describe("Client order id"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier"), + name: z.string().optional().describe("Address name"), + questionnaire: z.string().describe("Travel rule questionnaire"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + coin, + address, + amount, + withdrawOrderId, + network, + addressTag, + name, + questionnaire, + recvWindow, + }) => { + try { + const params: any = { + coin, + address, + amount, + questionnaire, + }; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawTravelRule(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Withdraw travel rule request submitted. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Withdraw travel rule request submitted. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit withdraw travel rule request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to submit withdraw travel rule request: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/server/base.ts b/src/server/base.ts index 9c5193e8..11ad6a6b 100644 --- a/src/server/base.ts +++ b/src/server/base.ts @@ -1,24 +1,28 @@ // src/server/base.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinance } from "../binance.js" -import Logger from "../utils/logger.js" +import { registerBinance } from "../binance.js"; +import { IS_TESTNET } from "../config/testnet.js"; +import Logger from "../utils/logger.js"; -// Create and start the MCP server export const startServer = () => { try { - // Create a new MCP server instance + const name = IS_TESTNET ? "binance-mcp (TESTNET)" : "binance-mcp"; + const description = IS_TESTNET + ? "MCP server for Binance Spot Test Network — only /api endpoints (spot trading & market data) are available" + : "MCP server for Binance exchange - spot trading, staking, wallet, NFT, pay, mining, and more"; + const server = new McpServer({ - name: "binance-mcp", + name, version: "1.0.0", - description: "MCP server for Binance exchange - spot trading, staking, wallet, NFT, pay, mining, and more" - }) + description, + }); + + registerBinance(server); - // Register all Binance modules - registerBinance(server) - return server + return server; } catch (error) { - Logger.error("Failed to initialize server:", error) - process.exit(1) + Logger.error("Failed to initialize server:", error); + process.exit(1); } -} +}; diff --git a/src/server/sse.ts b/src/server/sse.ts index d3463db9..6da61225 100644 --- a/src/server/sse.ts +++ b/src/server/sse.ts @@ -1,69 +1,226 @@ +import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; +import type { Request, Response } from "express"; +import type { Server } from "http"; +import type { IncomingMessage, ServerResponse } from "node:http"; + +import { randomUUID } from "node:crypto"; + +import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; +import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; +import cors from "cors"; + +import Logger from "../utils/logger.js"; + +import { startServer } from "./base.js"; + // src/server/sse.ts -import "dotenv/config" +// Credentials are not passed per-request here. They are loaded at process startup (see index.ts +// dotenv/config) and applied when config/binanceClient.ts is first required by tool handlers. +import "dotenv/config"; -import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js" -import express from "express" -import cors from "cors" +const PORT = process.env.PORT || 3002; -import Logger from "../utils/logger.js" -import { startServer } from "./base.js" +function ensureBinanceEnv(): void { + const key = process.env.BINANCE_API_KEY; + const secret = process.env.BINANCE_API_SECRET; + if (!key?.trim() || !secret?.trim()) { + Logger.warn( + "[SSE] BINANCE_API_KEY or BINANCE_API_SECRET is missing or empty. Signed API calls will fail.", + ); + } +} -const PORT = process.env.PORT || 3002 +/** Log the outbound IP this process uses (same as Binance would see). Helps debug IP whitelist / proxy issues. */ +async function logOutboundIp(): Promise { + try { + const res = await fetch("https://api.ipify.org?format=json"); + const data = (await res.json()) as { ip?: string }; + const ip = data?.ip ?? "(unknown)"; + Logger.info(`[SSE] Outbound IP (Binance will see this): ${ip}`); + } catch (err) { + Logger.warn( + "[SSE] Could not resolve outbound IP:", + err instanceof Error ? err.message : String(err), + ); + } +} + +/** Transport + Streamable HTTP handleRequest for routing and logging. */ +type StreamableTransportWithHandle = Transport & { + handleRequest(req: IncomingMessage, res: ServerResponse, parsedBody?: unknown): Promise; +}; + +/** + * How tool `content` flows when the Streamable HTTP server runs a tool: + * + * 1. Tool handler (e.g. getAccount.ts) returns { content: [{ type: "text", text: "..." }] }. + * 2. McpServer (SDK) CallTool request handler runs the handler and returns that object. + * 3. Server (SDK) validates it as CallToolResult and returns it from the tools/call handler. + * 4. Protocol (SDK) puts it in response.result and calls transport.send({ jsonrpc, id, result }). + * 5. StreamableHTTPServerTransport.send() writes the JSON to the response/SSE stream. + * + * This wrapper logs every tools/call (tool name). Request arguments and tool result content are + * logged only for names in {@link MCP_TOOLS_TO_LOG}. + */ + +/** MCP tool names for which we log request arguments and result content. Add names here as needed. */ +const MCP_TOOLS_TO_LOG = new Set(["BinanceNewOrder", "BinanceOrderOco", "BinanceGetOrder", "BinanceGetOpenOrders"]); -// Start the server in SSE mode -export const startSSEServer = async () => { +function shouldLogMcpToolContent(name: unknown): name is string { + return typeof name === "string" && MCP_TOOLS_TO_LOG.has(name); +} + +function wrapTransportWithToolLogging( + transport: StreamableHTTPServerTransport, +): StreamableTransportWithHandle { + const pendingToolCalls = new Map(); + + return { + get sessionId() { + return transport.sessionId; + }, + get onmessage() { + return transport.onmessage; + }, + set onmessage(handler: typeof transport.onmessage) { + transport.onmessage = handler; + }, + get onclose() { + return transport.onclose; + }, + set onclose(handler: typeof transport.onclose) { + transport.onclose = handler; + }, + get onerror() { + return transport.onerror; + }, + set onerror(handler: typeof transport.onerror) { + transport.onerror = handler; + }, + async start() { + return transport.start(); + }, + async close() { + return transport.close(); + }, + async send( + message: Parameters[0], + options?: Parameters[1], + ) { + const msg = message as { id?: string | number; result?: { content?: unknown } }; + if (msg?.result && msg.result.content !== undefined) { + const toolName = pendingToolCalls.get(msg.id as string | number); + if (toolName !== undefined) { + console.log( + "[MCP Streamable HTTP] tool result content", + `(tool: ${toolName})`, + JSON.stringify(msg.result.content), + ); + } + if (msg.id !== undefined) pendingToolCalls.delete(msg.id); + } + + return transport.send(message, options); + }, + async handleRequest(req: IncomingMessage, res: ServerResponse, parsedBody?: unknown) { + const body = parsedBody ?? (req as IncomingMessage & { body?: unknown }).body; + const parsed = typeof body === "string" ? JSON.parse(body as string) : body; + + if (parsed?.method === "tools/call" && parsed.params) { + const name = parsed.params.name; + if (typeof name === "string") { + console.log("[MCP Streamable HTTP] tools/call request", name); + if (shouldLogMcpToolContent(name)) { + console.log( + "[MCP Streamable HTTP] tools/call arguments", + name, + parsed.params.arguments, + ); + if (parsed.id !== undefined) pendingToolCalls.set(parsed.id, name); + } + } + } + + return transport.handleRequest(req, res, parsedBody ?? body); + }, + }; +} + +interface SessionEntry { + transport: StreamableTransportWithHandle; + server: Awaited>; +} + +// Start the server in Streamable HTTP mode (replaces deprecated SSE transport) +export const startSSEServer = async (): Promise => { try { - const app = express() - app.use(cors()) - app.use(express.json()) - - const server = startServer() - - // Store active transports - const transports: Map = new Map() - - // SSE endpoint - app.get("/sse", async (req, res) => { - const sessionId = req.query.sessionId as string || crypto.randomUUID() - - Logger.info(`New SSE connection: ${sessionId}`) - - const transport = new SSEServerTransport("/message", res) - transports.set(sessionId, transport) - - res.on("close", () => { - Logger.info(`SSE connection closed: ${sessionId}`) - transports.delete(sessionId) - }) - - await server.connect(transport) - }) - - // Message endpoint - app.post("/message", async (req, res) => { - const sessionId = req.query.sessionId as string - const transport = transports.get(sessionId) - - if (!transport) { - res.status(404).json({ error: "Session not found" }) - return + // Default createMcpExpressApp() uses host 127.0.0.1 → localhostHostValidation() + // rejects any other Host (403). Private URLs like binance-mcp.railway.internal + // must be allowed when the process listens on 0.0.0.0 (Railway, Docker, LAN). + const app = createMcpExpressApp({ host: "0.0.0.0" }); + app.use(cors()); + + const sessions = new Map(); + + const createNewSession = (): SessionEntry => { + const server = startServer(); + const rawTransport = new StreamableHTTPServerTransport({ + sessionIdGenerator: () => randomUUID(), + onsessioninitialized: (sessionId) => { + sessions.set(sessionId, { transport, server }); + Logger.info(`Streamable HTTP session initialized: ${sessionId}`); + }, + onsessionclosed: (sessionId) => { + const entry = sessions.get(sessionId); + if (entry) { + sessions.delete(sessionId); + entry.server.close().catch(() => undefined); + Logger.info(`Streamable HTTP session closed: ${sessionId}`); + } + }, + }); + const transport = wrapTransportWithToolLogging(rawTransport); + + return { transport, server }; + }; + + // Streamable HTTP handler (GET for SSE, POST for JSON-RPC) + const handleMcpRequest = async (req: Request, res: Response) => { + const sessionId = + req.get("mcp-session-id") ?? (req.headers["mcp-session-id"] as string | undefined); + let entry: SessionEntry | undefined = sessionId ? sessions.get(sessionId) : undefined; + + if (!entry) { + entry = createNewSession(); + await entry.server.connect(entry.transport); } - await transport.handlePostMessage(req, res) - }) + await entry.transport.handleRequest(req, res, req.body); + }; + + // Primary endpoint (Streamable HTTP) + app.all("/mcp", handleMcpRequest); + // Alias for MCP Inspector and clients that default to /sse. + // Use transport type "streamable-http" in the inspector (not deprecated "sse") so the + // client sends POST initialize before GET; otherwise the server returns 400. + app.all("/sse", handleMcpRequest); // Health check app.get("/health", (req, res) => { - res.json({ status: "ok", mode: "sse" }) - }) + res.json({ status: "ok", mode: "streamable-http" }); + }); - app.listen(PORT, () => { - Logger.info(`Binance MCP Server running on SSE mode at http://localhost:${PORT}`) - Logger.info(`SSE endpoint: http://localhost:${PORT}/sse`) - }) + const httpServer = app.listen(PORT, async () => { + Logger.info(`Binance MCP Server running in Streamable HTTP mode at http://localhost:${PORT}`); + Logger.info(`MCP endpoints: http://localhost:${PORT}/mcp and http://localhost:${PORT}/sse`); + ensureBinanceEnv(); + await logOutboundIp(); + }); - return server + return httpServer; } catch (error) { - Logger.error("Error starting Binance MCP SSE server:", error) + Logger.error("Error starting Binance MCP Streamable HTTP server:", error); + + return undefined; } -} +}; diff --git a/src/server/stdio.ts b/src/server/stdio.ts index 3bc6e96e..b3506f2f 100644 --- a/src/server/stdio.ts +++ b/src/server/stdio.ts @@ -1,32 +1,34 @@ -// src/server/stdio.ts -import "dotenv/config" +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; + +import Logger from "../utils/logger.js"; -import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" +import { startServer } from "./base.js"; -import Logger from "../utils/logger.js" -import { startServer } from "./base.js" +// src/server/stdio.ts +import "dotenv/config"; // Start the server in stdio mode export const startStdioServer = async () => { try { - const server = startServer() - const transport = new StdioServerTransport() - - Logger.info("Binance MCP Server running on stdio mode") + const server = startServer(); + const transport = new StdioServerTransport(); + + Logger.info("Binance MCP Server running on stdio mode"); transport.onmessage = (message) => { - Logger.debug("Received message:", message) - } + Logger.debug("Received message:", message); + }; transport.onclose = () => { - Logger.info("Stdio server closed") - } + Logger.info("Stdio server closed"); + }; transport.onerror = (error) => { - Logger.error("Stdio server error:", error) - } + Logger.error("Stdio server error:", error); + }; + + await server.connect(transport); - await server.connect(transport) - return server + return server; } catch (error) { - Logger.error("Error starting Binance MCP Stdio server:", error) + Logger.error("Error starting Binance MCP Stdio server:", error); } -} +}; diff --git a/src/tools/account/index.ts b/src/tools/account/index.ts index cb3731a7..d6f7b87c 100644 --- a/src/tools/account/index.ts +++ b/src/tools/account/index.ts @@ -1,11 +1,13 @@ // src/tools/account/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Account-related tools for Binance.US - * + * * Account endpoints provide access to: * - Account balances and permissions * - Trade history @@ -14,199 +16,246 @@ import { makeSignedRequest } from "../../config/binanceUsClient.js"; * - 30-day trading volume */ export function registerAccountTools(server: McpServer) { - // ===================================================== - // binance_us_account_info - // GET /api/v3/account - // ===================================================== - server.tool( - "binance_us_account_info", + // ===================================================== + // binance_us_account_info + // GET /api/v3/account + // ===================================================== + server.registerTool( + "binance_us_account_info", + { + description: "Get current account information including balances and permissions. Returns all asset balances (free and locked), account permissions, and trading status.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000. Default: 5000"), - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/api/v3/account", params); - - // Format balances for readability - const nonZeroBalances = data.balances?.filter( - (b: { free: string; locked: string }) => - parseFloat(b.free) > 0 || parseFloat(b.locked) > 0 - ) || []; - - return { - content: [{ - type: "text", - text: JSON.stringify({ - makerCommission: data.makerCommission, - takerCommission: data.takerCommission, - buyerCommission: data.buyerCommission, - sellerCommission: data.sellerCommission, - canTrade: data.canTrade, - canWithdraw: data.canWithdraw, - canDeposit: data.canDeposit, - updateTime: data.updateTime, - accountType: data.accountType, - balances: nonZeroBalances, - permissions: data.permissions - }, null, 2) - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get account info: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================== - // binance_us_my_trades - // GET /api/v3/myTrades - // ===================================================== - server.tool( - "binance_us_my_trades", + inputSchema: { + recvWindow: z + .number() + .optional() + .describe("The value cannot be greater than 60000. Default: 5000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/api/v3/account", params); + + // Format balances for readability + const nonZeroBalances = + data.balances?.filter( + (b: { free: string; locked: string }) => + parseFloat(b.free) > 0 || parseFloat(b.locked) > 0, + ) || []; + + return { + content: [ + { + type: "text", + text: JSON.stringify( + { + makerCommission: data.makerCommission, + takerCommission: data.takerCommission, + buyerCommission: data.buyerCommission, + sellerCommission: data.sellerCommission, + canTrade: data.canTrade, + canWithdraw: data.canWithdraw, + canDeposit: data.canDeposit, + updateTime: data.updateTime, + accountType: data.accountType, + balances: nonZeroBalances, + permissions: data.permissions, + }, + null, + 2, + ), + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get account info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_my_trades + // GET /api/v3/myTrades + // ===================================================== + server.registerTool( + "binance_us_my_trades", + { + description: "Get trade history for a specific trading pair. Returns executed trades including price, quantity, commission, and timestamps.", - { - symbol: z.string().describe("Trading pair symbol, e.g., BTCUSD, ETHUSD"), - orderId: z.number().optional().describe("Filter by order ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - fromId: z.number().optional().describe("Trade ID to fetch from. Default gets most recent trades."), - limit: z.number().optional().describe("Number of trades to return. Default: 500, Max: 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { - try { - const params: Record = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/api/v3/myTrades", params); - - return { - content: [{ - type: "text", - text: `Trade history for ${symbol}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get trade history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================== - // binance_us_rate_limits - // GET /api/v3/rateLimit/order - // ===================================================== - server.tool( - "binance_us_rate_limits", + inputSchema: { + symbol: z.string().describe("Trading pair symbol, e.g., BTCUSD, ETHUSD"), + orderId: z.number().optional().describe("Filter by order ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + fromId: z + .number() + .optional() + .describe("Trade ID to fetch from. Default gets most recent trades."), + limit: z + .number() + .optional() + .describe("Number of trades to return. Default: 500, Max: 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { + try { + const params: Record = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/api/v3/myTrades", params); + + return { + content: [ + { + type: "text", + text: `Trade history for ${symbol}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get trade history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_rate_limits + // GET /api/v3/rateLimit/order + // ===================================================== + server.registerTool( + "binance_us_rate_limits", + { + description: "Get current trade order count rate limits for all time intervals. Shows how many orders you can place within each interval.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/api/v3/rateLimit/order", params); - - return { - content: [{ - type: "text", - text: `Order Rate Limits:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get rate limits: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================== - // binance_us_trade_fee - // GET /sapi/v1/asset/query/trading-fee - // ===================================================== - server.tool( - "binance_us_trade_fee", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/api/v3/rateLimit/order", params); + + return { + content: [ + { + type: "text", + text: `Order Rate Limits:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get rate limits: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_trade_fee + // GET /sapi/v1/asset/query/trading-fee + // ===================================================== + server.registerTool( + "binance_us_trade_fee", + { + description: "Get your current maker & taker fee rates for spot trading based on your VIP level. BNB fee discount (25% off) is not factored in.", - { - symbol: z.string().optional().describe("Trading pair symbol. If not specified, returns fees for all symbols."), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ symbol, recvWindow }) => { - try { - const params: Record = {}; - if (symbol !== undefined) params.symbol = symbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/asset/query/trading-fee", params); - - return { - content: [{ - type: "text", - text: `Trading Fees:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get trading fees: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================== - // binance_us_trade_volume - // GET /sapi/v1/asset/query/trading-volume - // ===================================================== - server.tool( - "binance_us_trade_volume", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Trading pair symbol. If not specified, returns fees for all symbols."), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, recvWindow }) => { + try { + const params: Record = {}; + if (symbol !== undefined) params.symbol = symbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/asset/query/trading-fee", params); + + return { + content: [ + { + type: "text", + text: `Trading Fees:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get trading fees: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_trade_volume + // GET /sapi/v1/asset/query/trading-volume + // ===================================================== + server.registerTool( + "binance_us_trade_volume", + { + description: "Get total trade volume for the past 30 days. Volume is calculated on a rolling basis every day at 0:00 AM (UTC).", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/asset/query/trading-volume", params); - - return { - content: [{ - type: "text", - text: `Past 30 Days Trading Volume: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get trading volume: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/asset/query/trading-volume", params); + + return { + content: [ + { + type: "text", + text: `Past 30 Days Trading Volume: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get trading volume: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/TwapNewTrade.ts b/src/tools/binance-algo/future-algo/TwapNewTrade.ts index 2bae1220..89aef9f6 100644 --- a/src/tools/binance-algo/future-algo/TwapNewTrade.ts +++ b/src/tools/binance-algo/future-algo/TwapNewTrade.ts @@ -1,81 +1,95 @@ // src/tools/binance-algo/future-algo/TwapNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceTwapNewTrade(server: McpServer) { - server.tool( - "BinanceTimeWeightedAveragePriceNewOrder", + server.registerTool( + "BinanceTimeWeightedAveragePriceNewOrder", + { + description: "The Time-Weighted Average Price (TWAP) New Order API allows users to place a TWAP order on USDⓈ-M Contracts in Binance Futures. TWAP orders execute gradually over a specified duration to achieve a better average execution price while minimizing market impact.", - { - symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - positionSide: z - .enum(["BOTH", "LONG", "SHORT"]) - .optional() - .describe("Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. Must be sent in Hedge Mode."), - quantity: z - .number() - .positive() - .min(1000) - .max(1000000) - .describe("Quantity of base asset; Notional must be between 1,000 and 1,000,000 USDT"), - duration: z - .number() - .int() - .min(300) - .max(86400) - .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), - clientAlgoId: z.string().length(32).optional().describe("A unique 32-character ID among Algo orders"), - reduceOnly: z - .boolean() - .optional() - .describe("true or false. Default false; Cannot be sent in Hedge Mode or when opening a position"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.timeWeightedAveragePriceFutureAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - duration: params.duration, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe( + "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. Must be sent in Hedge Mode.", + ), + quantity: z + .number() + .positive() + .min(1000) + .max(1000000) + .describe("Quantity of base asset; Notional must be between 1,000 and 1,000,000 USDT"), + duration: z + .number() + .int() + .min(300) + .max(86400) + .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe("A unique 32-character ID among Algo orders"), + reduceOnly: z + .boolean() + .optional() + .describe( + "true or false. Default false; Cannot be sent in Hedge Mode or when opening a position", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.timeWeightedAveragePriceFutureAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + duration: params.duration, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place a TWAP order on: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place a TWAP order on: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/VPNewTrade.ts b/src/tools/binance-algo/future-algo/VPNewTrade.ts index 904623be..66056935 100644 --- a/src/tools/binance-algo/future-algo/VPNewTrade.ts +++ b/src/tools/binance-algo/future-algo/VPNewTrade.ts @@ -1,78 +1,90 @@ // src/tools/binance-algo/future-algo/VPNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceVPNewTrade(server: McpServer) { - server.tool( - "BinanceVolumeParticipationNewTrade", + server.registerTool( + "BinanceVolumeParticipationNewTrade", + { + description: "The Volume Participation (VP) New Order API allows users to place a VP order on USDⓈ-M Contracts in Binance Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - positionSide: z - .enum(["BOTH", "LONG", "SHORT"]) - .optional() - .describe( - "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. It must be sent in Hedge Mode." - ), - quantity: z - .number() - .positive() - .min(10000) - .max(1000000) - .describe("Quantity of base asset; Notional must be between 10,000 and 1,000,000 USDT"), - urgency: z.enum(["LOW", "MEDIUM", "HIGH"]).describe("Execution speed: LOW, MEDIUM, HIGH"), - clientAlgoId: z.string().length(32).optional().describe("A unique 32-character ID among Algo orders"), - reduceOnly: z - .boolean() - .optional() - .describe("true or false. Default false; Cannot be sent in Hedge Mode or when opening a position"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent"), - recvWindow: z.number().int().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.volumeParticipationFutureAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - urgency: params.urgency, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), - recvWindow: params.recvWindow - }); + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe( + "Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode. It must be sent in Hedge Mode.", + ), + quantity: z + .number() + .positive() + .min(10000) + .max(1000000) + .describe("Quantity of base asset; Notional must be between 10,000 and 1,000,000 USDT"), + urgency: z.enum(["LOW", "MEDIUM", "HIGH"]).describe("Execution speed: LOW, MEDIUM, HIGH"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe("A unique 32-character ID among Algo orders"), + reduceOnly: z + .boolean() + .optional() + .describe( + "true or false. Default false; Cannot be sent in Hedge Mode or when opening a position", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + recvWindow: z.number().int().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.volumeParticipationFutureAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + urgency: params.urgency, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.clientAlgoId && { clientAlgoId: params.clientAlgoId }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + recvWindow: params.recvWindow, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `VP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `VP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place a VP order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place a VP order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/cancelAlgoOrder.ts b/src/tools/binance-algo/future-algo/cancelAlgoOrder.ts index cc80a4a3..4fc24f40 100644 --- a/src/tools/binance-algo/future-algo/cancelAlgoOrder.ts +++ b/src/tools/binance-algo/future-algo/cancelAlgoOrder.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/future-algo/cancelAlgoOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureCancelAlgoOrder(server: McpServer) { - server.tool( - "BinanceFutureCancelAlgoOrder", + server.registerTool( + "BinanceFutureCancelAlgoOrder", + { + description: "The Cancel Algo Order API allows users to cancel an active algorithmic order on USDⓈ-M Contracts in Binance Futures.", - { - algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.cancelAlgoOrderFutureAlgo({ - algoId: params.algoId, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.cancelAlgoOrderFutureAlgo({ + algoId: params.algoId, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to cancel Algo Order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to cancel Algo Order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts b/src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts index 14a2de89..32dda635 100644 --- a/src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts +++ b/src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts @@ -1,43 +1,49 @@ // src/tools/binance-algo/future-algo/currentAlgoOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureCurrentAlgoOpenOrders(server: McpServer) { - server.tool( - "BinanceFutureCurrentAlgoOpenOrders", + server.registerTool( + "BinanceFutureCurrentAlgoOpenOrders", + { + description: "The Query Current Algo Open Orders API retrieves a list of currently active algorithmic orders for USDⓈ-M Contracts in Binance Futures.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersFutureAlgo({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersFutureAlgo({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Currently active algorithmic orders. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Currently active algorithmic orders. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Current Algo Open Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Current Algo Open Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/historicalAlgoOrder.ts b/src/tools/binance-algo/future-algo/historicalAlgoOrder.ts index bf3f942d..2e693e63 100644 --- a/src/tools/binance-algo/future-algo/historicalAlgoOrder.ts +++ b/src/tools/binance-algo/future-algo/historicalAlgoOrder.ts @@ -1,62 +1,76 @@ // src/tools/binance-algo/future-algo/historicalAlgoOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureHistoricalAlgoOrder(server: McpServer) { - server.tool( - "BinanceFutureHistoricalAlgoOrder", + server.registerTool( + "BinanceFutureHistoricalAlgoOrder", + { + description: "The Query Historical Algo Orders API retrieves a list of past algorithmic orders for USDⓈ-M Contracts in Binance Futures.", - { - symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryHistoricalAlgoOrdersFutureAlgo({ - ...(params.symbol !== undefined && { symbol: params.symbol }), - ...(params.side !== undefined && { side: params.side }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.page !== undefined && { page: params.page }), - ...(params.pageSize !== undefined && { pageSize: params.pageSize }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryHistoricalAlgoOrdersFutureAlgo({ + ...(params.symbol !== undefined && { symbol: params.symbol }), + ...(params.side !== undefined && { side: params.side }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.page !== undefined && { page: params.page }), + ...(params.pageSize !== undefined && { pageSize: params.pageSize }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Historical Algo Orders retrieves successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Historical Algo Orders retrieves successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Historical Algo Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Historical Algo Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/future-algo/index.ts b/src/tools/binance-algo/future-algo/index.ts index 9dfdc703..503ac247 100644 --- a/src/tools/binance-algo/future-algo/index.ts +++ b/src/tools/binance-algo/future-algo/index.ts @@ -1,28 +1,29 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceVPNewTrade } from "./VPNewTrade.js"; -import { registerBinanceFutureHistoricalAlgoOrder } from "./historicalAlgoOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFutureCancelAlgoOrder } from "./cancelAlgoOrder.js"; import { registerBinanceFutureCurrentAlgoOpenOrders } from "./currentAlgoOpenOrders.js"; +import { registerBinanceFutureHistoricalAlgoOrder } from "./historicalAlgoOrder.js"; import { registerBinanceFutureSubOrders } from "./subOrders.js"; import { registerBinanceTwapNewTrade } from "./TwapNewTrade.js"; +import { registerBinanceVPNewTrade } from "./VPNewTrade.js"; export function registerBinanceAlgoFutureApiTools(server: McpServer) { - // Registers a new VP (Volume Participation) trade - registerBinanceVPNewTrade(server); + // Registers a new VP (Volume Participation) trade + registerBinanceVPNewTrade(server); - // Registers a new TWAP (Time-Weighted Average Price) trade - registerBinanceTwapNewTrade(server); + // Registers a new TWAP (Time-Weighted Average Price) trade + registerBinanceTwapNewTrade(server); - // Registers functionality to cancel an algorithmic order - registerBinanceFutureCancelAlgoOrder(server); + // Registers functionality to cancel an algorithmic order + registerBinanceFutureCancelAlgoOrder(server); - // Registers API to query sub-orders of an algorithmic order - registerBinanceFutureSubOrders(server); + // Registers API to query sub-orders of an algorithmic order + registerBinanceFutureSubOrders(server); - // Registers API to retrieve currently open algorithmic orders - registerBinanceFutureCurrentAlgoOpenOrders(server); + // Registers API to retrieve currently open algorithmic orders + registerBinanceFutureCurrentAlgoOpenOrders(server); - // Registers API to fetch historical algorithmic orders - registerBinanceFutureHistoricalAlgoOrder(server); + // Registers API to fetch historical algorithmic orders + registerBinanceFutureHistoricalAlgoOrder(server); } diff --git a/src/tools/binance-algo/future-algo/subOrders.ts b/src/tools/binance-algo/future-algo/subOrders.ts index cb334943..f36cbc6d 100644 --- a/src/tools/binance-algo/future-algo/subOrders.ts +++ b/src/tools/binance-algo/future-algo/subOrders.ts @@ -1,58 +1,64 @@ // src/tools/binance-algo/future-algo/subOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceFutureSubOrders(server: McpServer) { - server.tool( - "BinanceFutureSubOrders", + server.registerTool( + "BinanceFutureSubOrders", + { + description: "The Sub Orders API retrieves sub-orders associated with a specified algoId for USDⓈ-M Contracts in Binance Futures.", - { - algoId: z.number().int().describe("Algo order ID"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.querySubOrdersFutureAlgo({ - algoId: params.algoId, - page: params.page, - pageSize: params.pageSize, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.querySubOrdersFutureAlgo({ + algoId: params.algoId, + page: params.page, + pageSize: params.pageSize, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub Orders retrieved successfully for id ${ + params.algoId + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Sub Orders retrieved successfully for id ${ - params.algoId - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve retrieve sub-orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve retrieve sub-orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/index.ts b/src/tools/binance-algo/index.ts index ebbeb993..32267f55 100644 --- a/src/tools/binance-algo/index.ts +++ b/src/tools/binance-algo/index.ts @@ -1,10 +1,11 @@ // src/tools/binance-spot/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceAlgoFutureApiTools } from "./future-algo/index.js"; import { registerBinanceAlgoSpotApiTools } from "./spot-algo/index.js"; export function registerBinanceAlgoTools(server: McpServer) { - // Algo API tools - registerBinanceAlgoFutureApiTools(server); - registerBinanceAlgoSpotApiTools(server); + // Algo API tools + registerBinanceAlgoFutureApiTools(server); + registerBinanceAlgoSpotApiTools(server); } diff --git a/src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts b/src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts index d69c2904..e2068e02 100644 --- a/src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts +++ b/src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/spot-algo/cancelOpenTWAPOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotCancelOpenTWAPOrder(server: McpServer) { - server.tool( - "BinanceSpotCancelOpenTWAPOrder", + server.registerTool( + "BinanceSpotCancelOpenTWAPOrder", + { + description: "The Cancel Algo Order API allows users to cancel an open TWAP algorithmic order for spot trading on Binance.", - { - algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.cancelAlgoOrderSpotAlgo({ - algoId: params.algoId, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID (e.g., 14511)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.cancelAlgoOrderSpotAlgo({ + algoId: params.algoId, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Algo order ${params.algoId} canceled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Cancel Algo Order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Cancel Algo Order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts b/src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts index c47bc2cc..ad57c20a 100644 --- a/src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts +++ b/src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts @@ -1,45 +1,51 @@ // src/tools/binance-algo/spot-algo/currentAlgoOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotCurrentAlgoOpenOrders(server: McpServer) { - server.tool( - "BinanceSpotCurrentAlgoOpenOrders", + server.registerTool( + "BinanceSpotCurrentAlgoOpenOrders", + { + description: "This API retrieves all open SPOT TWAP (Time-Weighted Average Price) orders on Binance.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersSpotAlgo({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryCurrentAlgoOpenOrdersSpotAlgo({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieve all open SPOT TWAP (Time-Weighted Average Price) orders. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieve all open SPOT TWAP (Time-Weighted Average Price) orders. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieves all open SPOT TWAP: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieves all open SPOT TWAP: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts b/src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts index aa95a22e..9c26464b 100644 --- a/src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts +++ b/src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts @@ -1,64 +1,78 @@ // src/tools/binance-algo/spot-algo/historicalAlgoOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { algoClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { algoClient } from "../../../config/binanceClient.js"; + export function registerBinanceSpotHistoricalAlgoOrders(server: McpServer) { - server.tool( - "BinanceSpotHistoricalAlgoOrders", + server.registerTool( + "BinanceSpotHistoricalAlgoOrders", + { + description: "This API retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance.", - { - symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.queryHistoricalAlgoOrdersSpotAlgo({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.side && { side: params.side }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().optional().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).optional().describe("Trading side (BUY or SELL)"), + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.queryHistoricalAlgoOrdersSpotAlgo({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.side && { side: params.side }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieves all historical SPOT TWAP (Time-Weighted Average Price) orders from Binance. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve all historical SPOT TWAP: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve all historical SPOT TWAP: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/spot-algo/index.ts b/src/tools/binance-algo/spot-algo/index.ts index d43c1f94..366e4f7d 100644 --- a/src/tools/binance-algo/spot-algo/index.ts +++ b/src/tools/binance-algo/spot-algo/index.ts @@ -1,24 +1,25 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSpotTwapNewTrade } from "./spotTWAPOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSpotCancelOpenTWAPOrder } from "./cancelOpenTWAPOrder.js"; -import { registerBinanceSpotSubOrders } from "./subOrders.js"; import { registerBinanceSpotCurrentAlgoOpenOrders } from "./currentAlgoOpenOrders.js"; import { registerBinanceSpotHistoricalAlgoOrders } from "./historicalAlgoOrders.js"; +import { registerBinanceSpotTwapNewTrade } from "./spotTWAPOrder.js"; +import { registerBinanceSpotSubOrders } from "./subOrders.js"; export function registerBinanceAlgoSpotApiTools(server: McpServer) { - // Register the TWAP (Time-Weighted Average Price) tool for placing new spot algo orders - registerBinanceSpotTwapNewTrade(server); + // Register the TWAP (Time-Weighted Average Price) tool for placing new spot algo orders + registerBinanceSpotTwapNewTrade(server); - // Register the tool for canceling open TWAP spot algo orders - registerBinanceSpotCancelOpenTWAPOrder(server); + // Register the tool for canceling open TWAP spot algo orders + registerBinanceSpotCancelOpenTWAPOrder(server); - // Register the tool to handle sub-orders created under a parent algo order - registerBinanceSpotSubOrders(server); + // Register the tool to handle sub-orders created under a parent algo order + registerBinanceSpotSubOrders(server); - // Register the tool to fetch currently open algo orders for spot trading - registerBinanceSpotCurrentAlgoOpenOrders(server); + // Register the tool to fetch currently open algo orders for spot trading + registerBinanceSpotCurrentAlgoOpenOrders(server); - // Register the tool to fetch historical algo orders for spot trading - registerBinanceSpotHistoricalAlgoOrders(server); + // Register the tool to fetch historical algo orders for spot trading + registerBinanceSpotHistoricalAlgoOrders(server); } diff --git a/src/tools/binance-algo/spot-algo/spotTWAPOrder.ts b/src/tools/binance-algo/spot-algo/spotTWAPOrder.ts index 60b6f055..0d69adf7 100644 --- a/src/tools/binance-algo/spot-algo/spotTWAPOrder.ts +++ b/src/tools/binance-algo/spot-algo/spotTWAPOrder.ts @@ -1,73 +1,81 @@ // src/tools/binance-algo/spot-algo/spotTwapNewTrade.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { algoClient } from "../../../config/binanceClient.js"; export function registerBinanceSpotTwapNewTrade(server: McpServer) { - server.tool( - "BinanceSpotTimeWeightedAveragePriceNewOrder", + server.registerTool( + "BinanceSpotTimeWeightedAveragePriceNewOrder", + { + description: "The TWAP (Time-Weighted Average Price) New Order API allows users to place TWAP algorithmic orders for USDⓈ-M Futures on Binance.", - { - symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), - quantity: z - .number() - .positive() - .describe( - "Quantity of base asset; Maximum notional per order is 200k, 2mm, or 10mm, depending on the symbol" - ), - duration: z - .number() - .int() - .min(300) - .max(86400) - .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), - clientAlgoId: z - .string() - .length(32) - .optional() - .describe("A unique 32-character ID among Algo orders. If not sent, a default value will be assigned"), - limitPrice: z - .number() - .positive() - .optional() - .describe("Limit price of the order; Defaults to market price if not sent") - }, - async (params) => { - try { - const response = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - duration: params.duration, - ...(params.clientAlgoId !== undefined && { clientAlgoId: params.clientAlgoId }), - ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }) - }); + inputSchema: { + symbol: z.string().describe("Trading symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Trading side (BUY or SELL)"), + quantity: z + .number() + .positive() + .describe( + "Quantity of base asset; Maximum notional per order is 200k, 2mm, or 10mm, depending on the symbol", + ), + duration: z + .number() + .int() + .min(300) + .max(86400) + .describe("Duration for TWAP orders in seconds. Must be between 300 and 86400"), + clientAlgoId: z + .string() + .length(32) + .optional() + .describe( + "A unique 32-character ID among Algo orders. If not sent, a default value will be assigned", + ), + limitPrice: z + .number() + .positive() + .optional() + .describe("Limit price of the order; Defaults to market price if not sent"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + duration: params.duration, + ...(params.clientAlgoId !== undefined && { clientAlgoId: params.clientAlgoId }), + ...(params.limitPrice !== undefined && { limitPrice: params.limitPrice }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ + params.symbol + }. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `TWAP order on USDⓈ-M Contracts placed successfully for ${ - params.symbol - }. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to place TWAP algorithmic orders for USDⓈ-M Futures on Binance: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to place TWAP algorithmic orders for USDⓈ-M Futures on Binance: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-algo/spot-algo/subOrders.ts b/src/tools/binance-algo/spot-algo/subOrders.ts index 6836d7b4..ba459141 100644 --- a/src/tools/binance-algo/spot-algo/subOrders.ts +++ b/src/tools/binance-algo/spot-algo/subOrders.ts @@ -1,58 +1,64 @@ // src/tools/binance-algo/spot-algo/subOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { algoClient } from "../../../config/binanceClient.js"; export function registerBinanceSpotSubOrders(server: McpServer) { - server.tool( - "BinanceSpotSubOrders", + server.registerTool( + "BinanceSpotSubOrders", + { + description: "The Query Sub Orders API retrieves details of sub-orders associated with a specific algorithmic (Algo) order for spot trading on Binance.", - { - algoId: z.number().int().describe("Algo order ID"), - page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .default(100) - .optional() - .describe("Number of results per page, MIN 1, MAX 100, default is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await algoClient.restAPI.querySubOrdersSpotAlgo({ - algoId: params.algoId, - ...(params.page !== undefined && { page: params.page }), - ...(params.pageSize !== undefined && { pageSize: params.pageSize }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algoId: z.number().int().describe("Algo order ID"), + page: z.number().int().min(1).default(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .default(100) + .optional() + .describe("Number of results per page, MIN 1, MAX 100, default is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await algoClient.restAPI.querySubOrdersSpotAlgo({ + algoId: params.algoId, + ...(params.page !== undefined && { page: params.page }), + ...(params.pageSize !== undefined && { pageSize: params.pageSize }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub Orders retrieved successfully for id${params.algoId}. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Sub Orders retrieved successfully for id${params.algoId}. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Query Sub Orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Query Sub Orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/changeIndexPlanStatus.ts b/src/tools/binance-auto-invest/changeIndexPlanStatus.ts index 39b62f77..5ed93a81 100644 --- a/src/tools/binance-auto-invest/changeIndexPlanStatus.ts +++ b/src/tools/binance-auto-invest/changeIndexPlanStatus.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/changeIndexPlanStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestChangeIndexPlanStatus(server: McpServer) { - server.tool( - "BinanceAutoInvestChangeIndexPlanStatus", - "Change the status of an index-linked auto-invest plan (pause/resume).", - { - indexId: z.number().int().describe("Index ID"), - status: z.enum(["PAUSED", "ONGOING"]).describe("New plan status"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.changeIndexPlanStatus({ - indexId: params.indexId, - status: params.status, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Index plan status changed to ${params.status}\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to change index plan status: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestChangeIndexPlanStatus", + { + description: "Change the status of an index-linked auto-invest plan (pause/resume).", + inputSchema: { + indexId: z.number().int().describe("Index ID"), + status: z.enum(["PAUSED", "ONGOING"]).describe("New plan status"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.changePlanStatus({ + indexId: params.indexId, + status: params.status, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Index plan status changed to ${params.status}\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to change index plan status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/changePlanStatus.ts b/src/tools/binance-auto-invest/changePlanStatus.ts index 3e189745..59875493 100644 --- a/src/tools/binance-auto-invest/changePlanStatus.ts +++ b/src/tools/binance-auto-invest/changePlanStatus.ts @@ -1,39 +1,43 @@ // src/tools/binance-auto-invest/changePlanStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestChangePlanStatus(server: McpServer) { - server.tool( - "BinanceAutoInvestChangePlanStatus", - "Change plan status (pause/resume) for auto-invest.", - { - planId: z.number().describe("Plan ID"), - status: z.enum(["ONGOING", "PAUSED", "REMOVED"]).describe("New plan status") - }, - async ({ planId, status }) => { - try { - const params: any = { planId, status }; - - const response = await autoInvestClient.restAPI.changePlanStatus(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Plan status changed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change plan status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestChangePlanStatus", + { + description: "Change plan status (pause/resume) for auto-invest.", + inputSchema: { + planId: z.number().describe("Plan ID"), + status: z.enum(["ONGOING", "PAUSED", "REMOVED"]).describe("New plan status"), + }, + }, + async ({ planId, status }) => { + try { + const params: any = { planId, status }; + + const response = await (autoInvestClient as any).restAPI.changePlanStatus(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Plan status changed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to change plan status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/createPlan.ts b/src/tools/binance-auto-invest/createPlan.ts index ef065873..b55afa5f 100644 --- a/src/tools/binance-auto-invest/createPlan.ts +++ b/src/tools/binance-auto-invest/createPlan.ts @@ -1,54 +1,74 @@ // src/tools/binance-auto-invest/createPlan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestCreatePlan(server: McpServer) { - server.tool( - "BinanceAutoInvestCreatePlan", - "Create an investment plan for auto-invest.", - { - sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).describe("Plan type"), - subscriptionAmount: z.number().describe("Subscription amount"), - subscriptionCycle: z.enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]).describe("Subscription cycle"), - subscriptionStartTime: z.string().describe("Subscription start time"), - sourceAsset: z.string().describe("Source asset (e.g., USDT)"), - flexibleAllowedToUse: z.boolean().optional().describe("Whether flexible products are allowed to use"), - details: z.string().describe("JSON array of plan details including targetAsset and percentage") - }, - async ({ sourceType, planType, subscriptionAmount, subscriptionCycle, subscriptionStartTime, sourceAsset, flexibleAllowedToUse, details }) => { - try { - const params: any = { - sourceType, - planType, - subscriptionAmount, - subscriptionCycle, - subscriptionStartTime, - sourceAsset, - details - }; - if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; - - const response = await autoInvestClient.restAPI.investmentPlanCreation(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Investment plan created successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create plan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestCreatePlan", + { + description: "Create an investment plan for auto-invest.", + inputSchema: { + sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), + planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).describe("Plan type"), + subscriptionAmount: z.number().describe("Subscription amount"), + subscriptionCycle: z + .enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) + .describe("Subscription cycle"), + subscriptionStartTime: z.string().describe("Subscription start time"), + sourceAsset: z.string().describe("Source asset (e.g., USDT)"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Whether flexible products are allowed to use"), + details: z + .string() + .describe("JSON array of plan details including targetAsset and percentage"), + }, + }, + async ({ + sourceType, + planType, + subscriptionAmount, + subscriptionCycle, + subscriptionStartTime, + sourceAsset, + flexibleAllowedToUse, + details, + }) => { + try { + const params: any = { + sourceType, + planType, + subscriptionAmount, + subscriptionCycle, + subscriptionStartTime, + sourceAsset, + details, + }; + if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; + + const response = await (autoInvestClient as any).restAPI.investmentPlanCreation(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Investment plan created successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create plan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/editPlan.ts b/src/tools/binance-auto-invest/editPlan.ts index fb820ff3..6b2af370 100644 --- a/src/tools/binance-auto-invest/editPlan.ts +++ b/src/tools/binance-auto-invest/editPlan.ts @@ -1,50 +1,71 @@ // src/tools/binance-auto-invest/editPlan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestEditPlan(server: McpServer) { - server.tool( - "BinanceAutoInvestEditPlan", - "Edit an existing investment plan for auto-invest.", - { - planId: z.number().describe("Plan ID to edit"), - subscriptionAmount: z.number().optional().describe("Subscription amount"), - subscriptionCycle: z.enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]).optional().describe("Subscription cycle"), - subscriptionStartTime: z.string().optional().describe("Subscription start time"), - sourceAsset: z.string().optional().describe("Source asset (e.g., USDT)"), - flexibleAllowedToUse: z.boolean().optional().describe("Whether flexible products are allowed to use"), - details: z.string().optional().describe("JSON array of plan details including targetAsset and percentage") - }, - async ({ planId, subscriptionAmount, subscriptionCycle, subscriptionStartTime, sourceAsset, flexibleAllowedToUse, details }) => { - try { - const params: any = { planId }; - if (subscriptionAmount !== undefined) params.subscriptionAmount = subscriptionAmount; - if (subscriptionCycle) params.subscriptionCycle = subscriptionCycle; - if (subscriptionStartTime) params.subscriptionStartTime = subscriptionStartTime; - if (sourceAsset) params.sourceAsset = sourceAsset; - if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; - if (details) params.details = details; - - const response = await autoInvestClient.restAPI.investmentPlanAdjustment(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Investment plan edited successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to edit plan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestEditPlan", + { + description: "Edit an existing investment plan for auto-invest.", + inputSchema: { + planId: z.number().describe("Plan ID to edit"), + subscriptionAmount: z.number().optional().describe("Subscription amount"), + subscriptionCycle: z + .enum(["H1", "H4", "H8", "H12", "WEEKLY", "DAILY", "MONTHLY", "BI_WEEKLY"]) + .optional() + .describe("Subscription cycle"), + subscriptionStartTime: z.string().optional().describe("Subscription start time"), + sourceAsset: z.string().optional().describe("Source asset (e.g., USDT)"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Whether flexible products are allowed to use"), + details: z + .string() + .optional() + .describe("JSON array of plan details including targetAsset and percentage"), + }, + }, + async ({ + planId, + subscriptionAmount, + subscriptionCycle, + subscriptionStartTime, + sourceAsset, + flexibleAllowedToUse, + details, + }) => { + try { + const params: any = { planId }; + if (subscriptionAmount !== undefined) params.subscriptionAmount = subscriptionAmount; + if (subscriptionCycle) params.subscriptionCycle = subscriptionCycle; + if (subscriptionStartTime) params.subscriptionStartTime = subscriptionStartTime; + if (sourceAsset) params.sourceAsset = sourceAsset; + if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; + if (details) params.details = details; + + const response = await (autoInvestClient as any).restAPI.investmentPlanAdjustment(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Investment plan edited successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to edit plan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getHistoryList.ts b/src/tools/binance-auto-invest/getHistoryList.ts index fe478468..b8e125b4 100644 --- a/src/tools/binance-auto-invest/getHistoryList.ts +++ b/src/tools/binance-auto-invest/getHistoryList.ts @@ -5,52 +5,67 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/getHistoryList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestGetHistoryList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetHistoryList", - "Get auto-invest transaction history. View all past purchases and investments.", - { - planId: z.number().int().optional().describe("Filter by plan ID"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - targetAsset: z.string().optional().describe("Filter by target asset"), - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]).optional().describe("Filter by plan type"), - size: z.number().int().max(100).optional().describe("Number of results. Default 10, max 100"), - current: z.number().int().optional().describe("Current page. Default 1"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getHistoryList({ - ...(params.planId && { planId: params.planId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.targetAsset && { targetAsset: params.targetAsset }), - ...(params.planType && { planType: params.planType }), - ...(params.size && { size: params.size }), - ...(params.current && { current: params.current }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `Auto-invest history:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get history: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetHistoryList", + { + description: "Get auto-invest transaction history. View all past purchases and investments.", + inputSchema: { + planId: z.number().int().optional().describe("Filter by plan ID"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + targetAsset: z.string().optional().describe("Filter by target asset"), + planType: z + .enum(["SINGLE", "PORTFOLIO", "INDEX", "ALL"]) + .optional() + .describe("Filter by plan type"), + size: z + .number() + .int() + .max(100) + .optional() + .describe("Number of results. Default 10, max 100"), + current: z.number().int().optional().describe("Current page. Default 1"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getHistoryList({ + ...(params.planId && { planId: params.planId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.targetAsset && { targetAsset: params.targetAsset }), + ...(params.planType && { planType: params.planType }), + ...(params.size && { size: params.size }), + ...(params.current && { current: params.current }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Auto-invest history:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getIndexInfo.ts b/src/tools/binance-auto-invest/getIndexInfo.ts index 623aacb1..997cb517 100644 --- a/src/tools/binance-auto-invest/getIndexInfo.ts +++ b/src/tools/binance-auto-invest/getIndexInfo.ts @@ -5,38 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/getIndexInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestGetIndexInfo(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexInfo", + server.registerTool( + "BinanceAutoInvestGetIndexInfo", + { + description: "Get information about auto-invest index portfolios. Index portfolios are pre-built diversified portfolios.", - { - indexId: z.number().int().optional().describe("Specific index ID to query"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getIndexInfo({ - ...(params.indexId && { indexId: params.indexId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Index portfolio info:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get index info: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + indexId: z.number().int().optional().describe("Specific index ID to query"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getIndexInfo({ + ...(params.indexId && { indexId: params.indexId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index portfolio info:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get index info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getIndexLinkedPlanPositionDetails.ts b/src/tools/binance-auto-invest/getIndexLinkedPlanPositionDetails.ts index 6cbb4ac9..ff91c1d6 100644 --- a/src/tools/binance-auto-invest/getIndexLinkedPlanPositionDetails.ts +++ b/src/tools/binance-auto-invest/getIndexLinkedPlanPositionDetails.ts @@ -5,38 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/getIndexLinkedPlanPositionDetails.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestGetIndexLinkedPlanPositionDetails(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexLinkedPlanPositionDetails", - "Get position details for an index-linked auto-invest plan.", - { - indexId: z.number().int().describe("Index ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getIndexLinkedPlanPositionDetails({ - indexId: params.indexId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Index-linked plan position details:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get position details: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetIndexLinkedPlanPositionDetails", + { + description: "Get position details for an index-linked auto-invest plan.", + inputSchema: { + indexId: z.number().int().describe("Index ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await ( + autoInvestClient as any + ).restAPI.queryIndexLinkedPlanPositionDetails({ + indexId: params.indexId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index-linked plan position details:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get position details: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getIndexLinkedPlanPositionList.ts b/src/tools/binance-auto-invest/getIndexLinkedPlanPositionList.ts index a5d3d26d..b99a48a0 100644 --- a/src/tools/binance-auto-invest/getIndexLinkedPlanPositionList.ts +++ b/src/tools/binance-auto-invest/getIndexLinkedPlanPositionList.ts @@ -1,38 +1,49 @@ // src/tools/binance-auto-invest/getIndexLinkedPlanPositionList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetIndexLinkedPlanPositionList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexLinkedPlanPositionList", - "Query index linked plan position details for auto-invest.", - { - indexId: z.number().describe("Index ID") - }, - async ({ indexId }) => { - try { - const params: any = { indexId }; - - const response = await autoInvestClient.restAPI.queryIndexLinkedPlanPositionDetails(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Index linked plan position list retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get index linked plan position list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetIndexLinkedPlanPositionList", + { + description: "Query index linked plan position details for auto-invest.", + inputSchema: { + indexId: z.number().describe("Index ID"), + }, + }, + async ({ indexId }) => { + try { + const params: any = { indexId }; + + const response = await ( + autoInvestClient as any + ).restAPI.queryIndexLinkedPlanPositionDetails(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index linked plan position list retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to get index linked plan position list: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getIndexLinkedPlanRebalanceHistory.ts b/src/tools/binance-auto-invest/getIndexLinkedPlanRebalanceHistory.ts index 8c528c1a..46c94660 100644 --- a/src/tools/binance-auto-invest/getIndexLinkedPlanRebalanceHistory.ts +++ b/src/tools/binance-auto-invest/getIndexLinkedPlanRebalanceHistory.ts @@ -1,46 +1,57 @@ // src/tools/binance-auto-invest/getIndexLinkedPlanRebalanceHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetIndexLinkedPlanRebalanceHistory(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexLinkedPlanRebalanceHistory", - "Query index linked plan rebalance history for auto-invest.", - { - indexId: z.number().describe("Index ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - size: z.number().optional().describe("Page size") - }, - async ({ indexId, startTime, endTime, current, size }) => { - try { - const params: any = { indexId }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (size !== undefined) params.size = size; - - const response = await autoInvestClient.restAPI.indexLinkedPlanRebalanceDetails(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Index linked plan rebalance history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get index linked plan rebalance history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetIndexLinkedPlanRebalanceHistory", + { + description: "Query index linked plan rebalance history for auto-invest.", + inputSchema: { + indexId: z.number().describe("Index ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + size: z.number().optional().describe("Page size"), + }, + }, + async ({ indexId, startTime, endTime, current, size }) => { + try { + const params: any = { indexId }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (size !== undefined) params.size = size; + + const response = await (autoInvestClient as any).restAPI.indexLinkedPlanRebalanceDetails( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index linked plan rebalance history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to get index linked plan rebalance history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getIndexUserSummary.ts b/src/tools/binance-auto-invest/getIndexUserSummary.ts index c17cc034..85e6f9b4 100644 --- a/src/tools/binance-auto-invest/getIndexUserSummary.ts +++ b/src/tools/binance-auto-invest/getIndexUserSummary.ts @@ -5,38 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/getIndexUserSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestGetIndexUserSummary(server: McpServer) { - server.tool( - "BinanceAutoInvestGetIndexUserSummary", + server.registerTool( + "BinanceAutoInvestGetIndexUserSummary", + { + description: "Get user's index-linked plan summary including total invested and current value.", - { - indexId: z.number().int().describe("Index ID to query"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getIndexUserSummary({ - indexId: params.indexId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Index user summary for index ${params.indexId}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get index user summary: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + indexId: z.number().int().describe("Index ID to query"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getIndexUserSummary({ + indexId: params.indexId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index user summary for index ${params.indexId}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get index user summary: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getOneTimePlans.ts b/src/tools/binance-auto-invest/getOneTimePlans.ts index d66567e7..03a227e2 100644 --- a/src/tools/binance-auto-invest/getOneTimePlans.ts +++ b/src/tools/binance-auto-invest/getOneTimePlans.ts @@ -1,40 +1,46 @@ // src/tools/binance-auto-invest/getOneTimePlans.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetOneTimePlans(server: McpServer) { - server.tool( - "BinanceAutoInvestGetOneTimePlans", - "Query holding details of the plan.", - { - planId: z.number().describe("Plan ID"), - requestId: z.string().optional().describe("Request ID") - }, - async ({ planId, requestId }) => { - try { - const params: any = { planId }; - if (requestId) params.requestId = requestId; - - const response = await autoInvestClient.restAPI.queryOneTimeTransactionStatus(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Plan details retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get plan details: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetOneTimePlans", + { + description: "Query holding details of the plan.", + inputSchema: { + planId: z.number().describe("Plan ID"), + requestId: z.string().optional().describe("Request ID"), + }, + }, + async ({ planId, requestId }) => { + try { + const params: any = { planId }; + if (requestId) params.requestId = requestId; + + const response = await (autoInvestClient as any).restAPI.queryOneTimeTransactionStatus( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Plan details retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get plan details: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getPlanList.ts b/src/tools/binance-auto-invest/getPlanList.ts index a57082bf..43ac0401 100644 --- a/src/tools/binance-auto-invest/getPlanList.ts +++ b/src/tools/binance-auto-invest/getPlanList.ts @@ -1,39 +1,43 @@ // src/tools/binance-auto-invest/getPlanList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetPlanList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetPlanList", - "Query auto-invest plan list.", - { - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).optional().describe("Plan type") - }, - async ({ planType }) => { - try { - const params: any = {}; - if (planType) params.planType = planType; - - const response = await autoInvestClient.restAPI.getListOfPlans(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Plan list retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get plan list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetPlanList", + { + description: "Query auto-invest plan list.", + inputSchema: { + planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).optional().describe("Plan type"), + }, + }, + async ({ planType }) => { + try { + const params: any = {}; + if (planType) params.planType = planType; + + const response = await (autoInvestClient as any).restAPI.getListOfPlans(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Plan list retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get plan list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getSourceAssetList.ts b/src/tools/binance-auto-invest/getSourceAssetList.ts index 5c96d9da..30a2a9c9 100644 --- a/src/tools/binance-auto-invest/getSourceAssetList.ts +++ b/src/tools/binance-auto-invest/getSourceAssetList.ts @@ -1,45 +1,52 @@ // src/tools/binance-auto-invest/getSourceAssetList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetSourceAssetList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetSourceAssetList", - "Get source asset list for auto-invest.", - { - usageType: z.string().optional().describe("Usage type"), - targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), - indexId: z.number().optional().describe("Index ID"), - flexibleAllowedToUse: z.boolean().optional().describe("Whether flexible products are allowed to use") - }, - async ({ usageType, targetAsset, indexId, flexibleAllowedToUse }) => { - try { - const params: any = {}; - if (usageType) params.usageType = usageType; - if (targetAsset) params.targetAsset = targetAsset; - if (indexId !== undefined) params.indexId = indexId; - if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; - - const response = await autoInvestClient.restAPI.querySourceAssetList(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Source asset list retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get source asset list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetSourceAssetList", + { + description: "Get source asset list for auto-invest.", + inputSchema: { + usageType: z.string().optional().describe("Usage type"), + targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), + indexId: z.number().optional().describe("Index ID"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Whether flexible products are allowed to use"), + }, + }, + async ({ usageType, targetAsset, indexId, flexibleAllowedToUse }) => { + try { + const params: any = {}; + if (usageType) params.usageType = usageType; + if (targetAsset) params.targetAsset = targetAsset; + if (indexId !== undefined) params.indexId = indexId; + if (flexibleAllowedToUse !== undefined) params.flexibleAllowedToUse = flexibleAllowedToUse; + + const response = await (autoInvestClient as any).restAPI.querySourceAssetList(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Source asset list retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get source asset list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getSubscriptionHistory.ts b/src/tools/binance-auto-invest/getSubscriptionHistory.ts index 0a9288d9..6540e606 100644 --- a/src/tools/binance-auto-invest/getSubscriptionHistory.ts +++ b/src/tools/binance-auto-invest/getSubscriptionHistory.ts @@ -1,51 +1,57 @@ // src/tools/binance-auto-invest/getSubscriptionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetSubscriptionHistory(server: McpServer) { - server.tool( - "BinanceAutoInvestGetSubscriptionHistory", - "Query subscription transaction history for auto-invest.", - { - planId: z.number().optional().describe("Plan ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), - planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).optional().describe("Plan type"), - current: z.number().optional().describe("Current page"), - size: z.number().optional().describe("Page size") - }, - async ({ planId, startTime, endTime, targetAsset, planType, current, size }) => { - try { - const params: any = {}; - if (planId !== undefined) params.planId = planId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (targetAsset) params.targetAsset = targetAsset; - if (planType) params.planType = planType; - if (current !== undefined) params.current = current; - if (size !== undefined) params.size = size; - - const response = await autoInvestClient.restAPI.querySubscriptionTransactionHistory(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Subscription history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get subscription history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetSubscriptionHistory", + { + description: "Query subscription transaction history for auto-invest.", + inputSchema: { + planId: z.number().optional().describe("Plan ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), + planType: z.enum(["SINGLE", "PORTFOLIO", "INDEX"]).optional().describe("Plan type"), + current: z.number().optional().describe("Current page"), + size: z.number().optional().describe("Page size"), + }, + }, + async ({ planId, startTime, endTime, targetAsset, planType, current, size }) => { + try { + const params: any = {}; + if (planId !== undefined) params.planId = planId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (targetAsset) params.targetAsset = targetAsset; + if (planType) params.planType = planType; + if (current !== undefined) params.current = current; + if (size !== undefined) params.size = size; + + const response = await ( + autoInvestClient as any + ).restAPI.querySubscriptionTransactionHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Subscription history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get subscription history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getTargetAssetList.ts b/src/tools/binance-auto-invest/getTargetAssetList.ts index f49b174d..bae9314c 100644 --- a/src/tools/binance-auto-invest/getTargetAssetList.ts +++ b/src/tools/binance-auto-invest/getTargetAssetList.ts @@ -1,43 +1,47 @@ // src/tools/binance-auto-invest/getTargetAssetList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetTargetAssetList(server: McpServer) { - server.tool( - "BinanceAutoInvestGetTargetAssetList", - "Get target asset list for auto-invest.", - { - targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), - size: z.number().optional().describe("Page size"), - current: z.number().optional().describe("Current page") - }, - async ({ targetAsset, size, current }) => { - try { - const params: any = {}; - if (targetAsset) params.targetAsset = targetAsset; - if (size !== undefined) params.size = size; - if (current !== undefined) params.current = current; - - const response = await autoInvestClient.restAPI.getTargetAssetList(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Target asset list retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get target asset list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetTargetAssetList", + { + description: "Get target asset list for auto-invest.", + inputSchema: { + targetAsset: z.string().optional().describe("Target asset (e.g., BTC)"), + size: z.number().optional().describe("Page size"), + current: z.number().optional().describe("Current page"), + }, + }, + async ({ targetAsset, size, current }) => { + try { + const params: any = {}; + if (targetAsset) params.targetAsset = targetAsset; + if (size !== undefined) params.size = size; + if (current !== undefined) params.current = current; + + const response = await (autoInvestClient as any).restAPI.getTargetAssetList(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Target asset list retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get target asset list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getTargetAssetROI.ts b/src/tools/binance-auto-invest/getTargetAssetROI.ts index 1410dd66..3c2bba5f 100644 --- a/src/tools/binance-auto-invest/getTargetAssetROI.ts +++ b/src/tools/binance-auto-invest/getTargetAssetROI.ts @@ -1,39 +1,45 @@ // src/tools/binance-auto-invest/getTargetAssetROI.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestGetTargetAssetROI(server: McpServer) { - server.tool( - "BinanceAutoInvestGetTargetAssetROI", - "Get target asset ROI data for auto-invest.", - { - targetAsset: z.string().describe("Target asset (e.g., BTC)"), - hisRoiType: z.enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "ONE_MONTH"]).describe("Historical ROI type") - }, - async ({ targetAsset, hisRoiType }) => { - try { - const params: any = { targetAsset, hisRoiType }; - - const response = await autoInvestClient.restAPI.getTargetAssetRoiData(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Target asset ROI data retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get target asset ROI: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestGetTargetAssetROI", + { + description: "Get target asset ROI data for auto-invest.", + inputSchema: { + targetAsset: z.string().describe("Target asset (e.g., BTC)"), + hisRoiType: z + .enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "ONE_MONTH"]) + .describe("Historical ROI type"), + }, + }, + async ({ targetAsset, hisRoiType }) => { + try { + const params: any = { targetAsset, hisRoiType }; + + const response = await (autoInvestClient as any).restAPI.getTargetAssetRoiData(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Target asset ROI data retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get target asset ROI: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/getTargetAssetRoiData.ts b/src/tools/binance-auto-invest/getTargetAssetRoiData.ts index 5f17b651..db4fa7b4 100644 --- a/src/tools/binance-auto-invest/getTargetAssetRoiData.ts +++ b/src/tools/binance-auto-invest/getTargetAssetRoiData.ts @@ -5,40 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/getTargetAssetRoiData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestGetTargetAssetRoiData(server: McpServer) { - server.tool( - "BinanceAutoInvestGetTargetAssetRoiData", + server.registerTool( + "BinanceAutoInvestGetTargetAssetRoiData", + { + description: "Get ROI (Return on Investment) data for auto-invest target assets. Shows historical performance.", - { - targetAsset: z.string().describe("Target asset (e.g., 'BTC', 'ETH')"), - hisRoiType: z.enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "SEVEN_DAY"]).describe("Historical ROI period"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getTargetAssetRoiData({ - targetAsset: params.targetAsset, - hisRoiType: params.hisRoiType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `ROI data for ${params.targetAsset} (${params.hisRoiType}):\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get ROI data: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + targetAsset: z.string().describe("Target asset (e.g., 'BTC', 'ETH')"), + hisRoiType: z + .enum(["FIVE_YEAR", "THREE_YEAR", "ONE_YEAR", "SIX_MONTH", "THREE_MONTH", "SEVEN_DAY"]) + .describe("Historical ROI period"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getTargetAssetRoiData({ + targetAsset: params.targetAsset, + hisRoiType: params.hisRoiType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `ROI data for ${params.targetAsset} (${params.hisRoiType}):\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get ROI data: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/index.ts b/src/tools/binance-auto-invest/index.ts index 4e4afa14..e88465ac 100644 --- a/src/tools/binance-auto-invest/index.ts +++ b/src/tools/binance-auto-invest/index.ts @@ -1,30 +1,30 @@ // src/tools/binance-auto-invest/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceAutoInvestGetTargetAssetList } from "./getTargetAssetList.js"; -import { registerBinanceAutoInvestGetSourceAssetList } from "./getSourceAssetList.js"; -import { registerBinanceAutoInvestGetTargetAssetROI } from "./getTargetAssetROI.js"; -import { registerBinanceAutoInvestGetPlanList } from "./getPlanList.js"; -import { registerBinanceAutoInvestGetOneTimePlans } from "./getOneTimePlans.js"; +import { registerBinanceAutoInvestChangePlanStatus } from "./changePlanStatus.js"; import { registerBinanceAutoInvestCreatePlan } from "./createPlan.js"; import { registerBinanceAutoInvestEditPlan } from "./editPlan.js"; -import { registerBinanceAutoInvestChangePlanStatus } from "./changePlanStatus.js"; import { registerBinanceAutoInvestGetIndexLinkedPlanPositionList } from "./getIndexLinkedPlanPositionList.js"; import { registerBinanceAutoInvestGetIndexLinkedPlanRebalanceHistory } from "./getIndexLinkedPlanRebalanceHistory.js"; +import { registerBinanceAutoInvestGetOneTimePlans } from "./getOneTimePlans.js"; +import { registerBinanceAutoInvestGetPlanList } from "./getPlanList.js"; +import { registerBinanceAutoInvestGetSourceAssetList } from "./getSourceAssetList.js"; import { registerBinanceAutoInvestGetSubscriptionHistory } from "./getSubscriptionHistory.js"; +import { registerBinanceAutoInvestGetTargetAssetList } from "./getTargetAssetList.js"; +import { registerBinanceAutoInvestGetTargetAssetROI } from "./getTargetAssetROI.js"; import { registerBinanceAutoInvestRedeemIndexLinkedPlan } from "./redeemIndexLinkedPlan.js"; export function registerBinanceAutoInvestTools(server: McpServer) { - registerBinanceAutoInvestGetTargetAssetList(server); - registerBinanceAutoInvestGetSourceAssetList(server); - registerBinanceAutoInvestGetTargetAssetROI(server); - registerBinanceAutoInvestGetPlanList(server); - registerBinanceAutoInvestGetOneTimePlans(server); - registerBinanceAutoInvestCreatePlan(server); - registerBinanceAutoInvestEditPlan(server); - registerBinanceAutoInvestChangePlanStatus(server); - registerBinanceAutoInvestGetIndexLinkedPlanPositionList(server); - registerBinanceAutoInvestGetIndexLinkedPlanRebalanceHistory(server); - registerBinanceAutoInvestGetSubscriptionHistory(server); - registerBinanceAutoInvestRedeemIndexLinkedPlan(server); + registerBinanceAutoInvestGetTargetAssetList(server); + registerBinanceAutoInvestGetSourceAssetList(server); + registerBinanceAutoInvestGetTargetAssetROI(server); + registerBinanceAutoInvestGetPlanList(server); + registerBinanceAutoInvestGetOneTimePlans(server); + registerBinanceAutoInvestCreatePlan(server); + registerBinanceAutoInvestEditPlan(server); + registerBinanceAutoInvestChangePlanStatus(server); + registerBinanceAutoInvestGetIndexLinkedPlanPositionList(server); + registerBinanceAutoInvestGetIndexLinkedPlanRebalanceHistory(server); + registerBinanceAutoInvestGetSubscriptionHistory(server); + registerBinanceAutoInvestRedeemIndexLinkedPlan(server); } diff --git a/src/tools/binance-auto-invest/oneTimeTransaction.ts b/src/tools/binance-auto-invest/oneTimeTransaction.ts index 34515e33..6c97f15a 100644 --- a/src/tools/binance-auto-invest/oneTimeTransaction.ts +++ b/src/tools/binance-auto-invest/oneTimeTransaction.ts @@ -5,58 +5,78 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/oneTimeTransaction.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestOneTimeTransaction(server: McpServer) { - server.tool( - "BinanceAutoInvestOneTimeTransaction", + server.registerTool( + "BinanceAutoInvestOneTimeTransaction", + { + description: "Execute a one-time auto-invest purchase. Buy crypto instantly without creating a recurring plan.", - { - sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), - subscriptionAmount: z.string().describe("Amount to invest in source asset"), - sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), - flexibleAllowedToUse: z.boolean().optional().describe("Allow using Flexible Savings balance"), - planId: z.number().int().optional().describe("Plan ID if investing in existing plan"), - indexId: z.number().int().optional().describe("Index ID for index portfolio"), - details: z.array(z.object({ - targetAsset: z.string().describe("Target asset to purchase"), - percentage: z.number().min(0).max(100).describe("Allocation percentage") - })).optional().describe("Target assets and allocations (for ad-hoc purchase)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.oneTimeTransaction({ - sourceType: params.sourceType, - subscriptionAmount: params.subscriptionAmount, - sourceAsset: params.sourceAsset, - ...(params.flexibleAllowedToUse !== undefined && { flexibleAllowedToUse: params.flexibleAllowedToUse }), - ...(params.planId && { planId: params.planId }), - ...(params.indexId && { indexId: params.indexId }), - ...(params.details && { details: JSON.stringify(params.details) }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ One-time investment executed!\n\nTransaction ID: ${data.transactionId || 'N/A'}\nAmount: ${params.subscriptionAmount} ${params.sourceAsset}\n\nDetails:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to execute one-time transaction: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + sourceType: z.enum(["MAIN_SITE", "TR"]).describe("Source type"), + subscriptionAmount: z.string().describe("Amount to invest in source asset"), + sourceAsset: z.string().describe("Source asset (e.g., 'USDT')"), + flexibleAllowedToUse: z + .boolean() + .optional() + .describe("Allow using Flexible Savings balance"), + planId: z.number().int().optional().describe("Plan ID if investing in existing plan"), + indexId: z.number().int().optional().describe("Index ID for index portfolio"), + details: z + .array( + z.object({ + targetAsset: z.string().describe("Target asset to purchase"), + percentage: z.number().min(0).max(100).describe("Allocation percentage"), + }), + ) + .optional() + .describe("Target assets and allocations (for ad-hoc purchase)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.oneTimeTransaction({ + sourceType: params.sourceType, + subscriptionAmount: params.subscriptionAmount, + sourceAsset: params.sourceAsset, + ...(params.flexibleAllowedToUse !== undefined && { + flexibleAllowedToUse: params.flexibleAllowedToUse, + }), + ...(params.planId && { planId: params.planId }), + ...(params.indexId && { indexId: params.indexId }), + ...(params.details && { details: JSON.stringify(params.details) }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ One-time investment executed!\n\nTransaction ID: ${data.transactionId || "N/A"}\nAmount: ${params.subscriptionAmount} ${params.sourceAsset}\n\nDetails:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to execute one-time transaction: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/rebalanceHistory.ts b/src/tools/binance-auto-invest/rebalanceHistory.ts index 17a0ef15..4821e41b 100644 --- a/src/tools/binance-auto-invest/rebalanceHistory.ts +++ b/src/tools/binance-auto-invest/rebalanceHistory.ts @@ -5,46 +5,59 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/rebalanceHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestRebalanceHistory(server: McpServer) { - server.tool( - "BinanceAutoInvestRebalanceHistory", + server.registerTool( + "BinanceAutoInvestRebalanceHistory", + { + description: "Get rebalance history for portfolio/index plans. Shows when and how allocations were rebalanced.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - size: z.number().int().max(100).optional().describe("Number of results. Default 10, max 100"), - current: z.number().int().optional().describe("Current page. Default 1"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.getRebalanceHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.size && { size: params.size }), - ...(params.current && { current: params.current }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `Rebalance history:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get rebalance history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + size: z + .number() + .int() + .max(100) + .optional() + .describe("Number of results. Default 10, max 100"), + current: z.number().int().optional().describe("Current page. Default 1"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.getRebalanceHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.size && { size: params.size }), + ...(params.current && { current: params.current }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Rebalance history:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get rebalance history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/redeemIndexLinkedPlan.ts b/src/tools/binance-auto-invest/redeemIndexLinkedPlan.ts index 667ca7bf..cf5648c3 100644 --- a/src/tools/binance-auto-invest/redeemIndexLinkedPlan.ts +++ b/src/tools/binance-auto-invest/redeemIndexLinkedPlan.ts @@ -1,41 +1,45 @@ // src/tools/binance-auto-invest/redeemIndexLinkedPlan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { autoInvestClient } from "../../config/binanceClient.js"; export function registerBinanceAutoInvestRedeemIndexLinkedPlan(server: McpServer) { - server.tool( - "BinanceAutoInvestRedeemIndexLinkedPlan", - "Redeem index linked plan for auto-invest.", - { - indexId: z.number().describe("Index ID"), - redemptionPercentage: z.number().describe("Redemption percentage (0-100)"), - requestId: z.string().optional().describe("Request ID for idempotency") - }, - async ({ indexId, redemptionPercentage, requestId }) => { - try { - const params: any = { indexId, redemptionPercentage }; - if (requestId) params.requestId = requestId; - - const response = await autoInvestClient.restAPI.indexLinkedPlanRedemption(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Index linked plan redeemed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to redeem index linked plan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestRedeemIndexLinkedPlan", + { + description: "Redeem index linked plan for auto-invest.", + inputSchema: { + indexId: z.number().describe("Index ID"), + redemptionPercentage: z.number().describe("Redemption percentage (0-100)"), + requestId: z.string().optional().describe("Request ID for idempotency"), + }, + }, + async ({ indexId, redemptionPercentage, requestId }) => { + try { + const params: any = { indexId, redemptionPercentage }; + if (requestId) params.requestId = requestId; + + const response = await (autoInvestClient as any).restAPI.indexLinkedPlanRedemption(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index linked plan redeemed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to redeem index linked plan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-auto-invest/redemption.ts b/src/tools/binance-auto-invest/redemption.ts index 15a7824a..5a7bba23 100644 --- a/src/tools/binance-auto-invest/redemption.ts +++ b/src/tools/binance-auto-invest/redemption.ts @@ -5,45 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-auto-invest/redemption.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { autoInvestClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { autoInvestClient } from "../../config/binanceClient.js"; + export function registerBinanceAutoInvestRedemption(server: McpServer) { - server.tool( - "BinanceAutoInvestRedemption", - "Redeem (sell) holdings from an auto-invest index-linked plan.", - { - indexId: z.number().int().describe("Index ID to redeem from"), - redemptionPercentage: z.number().min(0).max(100).describe("Percentage of holdings to redeem (0-100)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await autoInvestClient.restAPI.redemption({ - indexId: params.indexId, - redemptionPercentage: params.redemptionPercentage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Redemption executed!\n\nRedeemed ${params.redemptionPercentage}% from index ${params.indexId}\n\nDetails:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to redeem: ${errorMessage}` - }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceAutoInvestRedemption", + { + description: "Redeem (sell) holdings from an auto-invest index-linked plan.", + inputSchema: { + indexId: z.number().int().describe("Index ID to redeem from"), + redemptionPercentage: z + .number() + .min(0) + .max(100) + .describe("Percentage of holdings to redeem (0-100)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await (autoInvestClient as any).restAPI.redemption({ + indexId: params.indexId, + redemptionPercentage: params.redemptionPercentage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Redemption executed!\n\nRedeemed ${params.redemptionPercentage}% from index ${params.indexId}\n\nDetails:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to redeem: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-c2c/C2C/getC2CTradeHistory.ts b/src/tools/binance-c2c/C2C/getC2CTradeHistory.ts index 1570b7ad..b7d007b5 100644 --- a/src/tools/binance-c2c/C2C/getC2CTradeHistory.ts +++ b/src/tools/binance-c2c/C2C/getC2CTradeHistory.ts @@ -1,48 +1,54 @@ // src/tools/binance-c2c/getC2CTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { c2cClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { c2cClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetC2CTradeHistory(server: McpServer) { - server.tool( - "BinanceGetC2CTradeHistory", + server.registerTool( + "BinanceGetC2CTradeHistory", + { + description: "Allows the user to retrieve their own past C2C trades, including details such as asset type, trade direction (BUY/SELL), fiat currency used, trade status, and more.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await c2cClient.restAPI.getC2CTradeHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.page !== undefined && { page: params.page }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await c2cClient.restAPI.getC2CTradeHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.page !== undefined && { page: params.page }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved the past C2C trades. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the past C2C trades. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve users past C2C trades: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve users past C2C trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-c2c/index.ts b/src/tools/binance-c2c/index.ts index 782b9c95..1f0b1aeb 100644 --- a/src/tools/binance-c2c/index.ts +++ b/src/tools/binance-c2c/index.ts @@ -1,7 +1,8 @@ // src/tools/binance-c2c/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetC2CTradeHistory } from "./C2C/getC2CTradeHistory.js"; export function registerBinanceC2CTradeHistoryTools(server: McpServer) { - registerBinanceGetC2CTradeHistory(server); + registerBinanceGetC2CTradeHistory(server); } diff --git a/src/tools/binance-convert/index.ts b/src/tools/binance-convert/index.ts index 2ad2bf25..73e8df32 100644 --- a/src/tools/binance-convert/index.ts +++ b/src/tools/binance-convert/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-convert/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceConvertTradeTools } from "./trade-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertMarketDataTools } from "./market-data-api/index.js"; +import { registerBinanceConvertTradeTools } from "./trade-api/index.js"; export function registerBinanceConvertTools(server: McpServer) { - // Register tools for accessing market data from Binance Convert - registerBinanceConvertMarketDataTools(server); + // Register tools for accessing market data from Binance Convert + registerBinanceConvertMarketDataTools(server); - // Register tools for performing trades on Binance Convert - registerBinanceConvertTradeTools(server); + // Register tools for performing trades on Binance Convert + registerBinanceConvertTradeTools(server); } diff --git a/src/tools/binance-convert/market-data-api/index.ts b/src/tools/binance-convert/market-data-api/index.ts index 923f432b..325cb54b 100644 --- a/src/tools/binance-convert/market-data-api/index.ts +++ b/src/tools/binance-convert/market-data-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-convert/market-data-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceConvertQueryOrderQuantityPrecisionPerAsset } from "./queryOrderQuantityPrecisionPerAsset.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertGetListAllConvertPairs } from "./listAllConvertPairs.js"; +import { registerBinanceConvertQueryOrderQuantityPrecisionPerAsset } from "./queryOrderQuantityPrecisionPerAsset.js"; export function registerBinanceConvertMarketDataTools(server: McpServer) { - // Register the route to get a list of all supported convert trading pairs - registerBinanceConvertGetListAllConvertPairs(server); + // Register the route to get a list of all supported convert trading pairs + registerBinanceConvertGetListAllConvertPairs(server); - // Register the route to get quantity precision details for each asset - registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server); + // Register the route to get quantity precision details for each asset + registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server); } diff --git a/src/tools/binance-convert/market-data-api/listAllConvertPairs.ts b/src/tools/binance-convert/market-data-api/listAllConvertPairs.ts index 6f130319..08a9bb1f 100644 --- a/src/tools/binance-convert/market-data-api/listAllConvertPairs.ts +++ b/src/tools/binance-convert/market-data-api/listAllConvertPairs.ts @@ -1,45 +1,51 @@ // src/tools/binance-convert/market-data-api/listAllConvertPairs.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertGetListAllConvertPairs(server: McpServer) { - server.tool( - "BinanceConvertGetListAllConvertPairs", + server.registerTool( + "BinanceConvertGetListAllConvertPairs", + { + description: "Query available conversion pairs (like BTC to USDT), and shows the minimum and maximum allowed amounts for both the source and destination tokens.", - { - fromAsset: z.string().optional().describe("User spends coin"), - toAsset: z.string().optional().describe("User receives coin") - }, - async (params) => { - try { - const response = await convertClient.restAPI.listAllConvertPairs({ - ...(params.fromAsset && { fromAsset: params.fromAsset }), - ...(params.toAsset && { toAsset: params.toAsset }) - }); + inputSchema: { + fromAsset: z.string().optional().describe("User spends coin"), + toAsset: z.string().optional().describe("User receives coin"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.listAllConvertPairs({ + ...(params.fromAsset && { fromAsset: params.fromAsset }), + ...(params.toAsset && { toAsset: params.toAsset }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully queried available conversion pairs. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully queried available conversion pairs. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to query available conversion pairs: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to query available conversion pairs: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts b/src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts index 27c59705..a37b5c20 100644 --- a/src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts +++ b/src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts @@ -1,50 +1,56 @@ // src/tools/binance-convert/market-data-api/queryOrderQuantityPrecisionPerAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertQueryOrderQuantityPrecisionPerAsset(server: McpServer) { - server.tool( - "BinanceConvertQueryOrderQuantityPrecisionPerAsset", + server.registerTool( + "BinanceConvertQueryOrderQuantityPrecisionPerAsset", + { + description: "Retrieve decimal precision (fraction) information for each supported asset in the Convert feature.", - { - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.queryOrderQuantityPrecisionPerAsset({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.queryOrderQuantityPrecisionPerAsset({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved decimal precision information for each supported asset. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved decimal precision information for each supported asset. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve decimal precision (fraction) information: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve decimal precision (fraction) information: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/acceptQuote.ts b/src/tools/binance-convert/trade-api/acceptQuote.ts index 50189a97..3df62cc2 100644 --- a/src/tools/binance-convert/trade-api/acceptQuote.ts +++ b/src/tools/binance-convert/trade-api/acceptQuote.ts @@ -1,49 +1,55 @@ // src/tools/binance-convert/trade-api/acceptQuote.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertAcceptQuote(server: McpServer) { - server.tool( - "BinanceConvertAcceptQuote", + server.registerTool( + "BinanceConvertAcceptQuote", + { + description: "The API confirms and executes a token conversion using a previously received quote ID.", - { - quoteId: z.string().describe("Quote ID"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.acceptQuote({ - quoteId: params.quoteId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + quoteId: z.string().describe("Quote ID"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.acceptQuote({ + quoteId: params.quoteId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully executed the token conversion. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully executed the token conversion. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to execute a token conversion : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to execute a token conversion : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/cancelLimitOrder.ts b/src/tools/binance-convert/trade-api/cancelLimitOrder.ts index 0e960cc2..4da9c70d 100644 --- a/src/tools/binance-convert/trade-api/cancelLimitOrder.ts +++ b/src/tools/binance-convert/trade-api/cancelLimitOrder.ts @@ -1,49 +1,55 @@ // src/tools/binance-convert/trade-api/cancelLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertCancelLimitOrder(server: McpServer) { - server.tool( - "BinanceConvertCancelLimitOrder", + server.registerTool( + "BinanceConvertCancelLimitOrder", + { + description: "Cancels a previously placed limit order using the orderId and returns the cancellation status along with the orderId.", - { - orderId: z.number().int().describe("The orderId from placeOrder API"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.cancelLimitOrder({ - orderId: params.orderId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + orderId: z.number().int().describe("The orderId from placeOrder API"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.cancelLimitOrder({ + orderId: params.orderId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Canceled the placed limit order. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Canceled the placed limit order. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to placed limit order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to placed limit order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/getConvertTradeHistory.ts b/src/tools/binance-convert/trade-api/getConvertTradeHistory.ts index 6da43a22..8c8fbe37 100644 --- a/src/tools/binance-convert/trade-api/getConvertTradeHistory.ts +++ b/src/tools/binance-convert/trade-api/getConvertTradeHistory.ts @@ -1,56 +1,62 @@ // src/tools/binance-convert/trade-api/getConvertTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetConvertTradeHistory(server: McpServer) { - server.tool( - "BinanceGetConvertTradeHistory", + server.registerTool( + "BinanceGetConvertTradeHistory", + { + description: "The API retrieves your token conversion trade history within a specified time range, with support for pagination using the limit parameter (up to 1000 records).", - { - startTime: z.number().int().describe("Start time in milliseconds"), - endTime: z.number().int().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(1000, "Limit cannot be greater than 1000") - .optional() - .describe("Default 100, Max 1000"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.getConvertTradeHistory({ - startTime: params.startTime, - endTime: params.endTime, - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().describe("Start time in milliseconds"), + endTime: z.number().int().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(1000, "Limit cannot be greater than 1000") + .optional() + .describe("Default 100, Max 1000"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.getConvertTradeHistory({ + startTime: params.startTime, + endTime: params.endTime, + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved your token conversion trade history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved your token conversion trade history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve your token conversion: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve your token conversion: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/index.ts b/src/tools/binance-convert/trade-api/index.ts index a7efa11e..86128d99 100644 --- a/src/tools/binance-convert/trade-api/index.ts +++ b/src/tools/binance-convert/trade-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-convert/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceConvertAcceptQuote } from "./acceptQuote.js"; import { registerBinanceConvertCancelLimitOrder } from "./cancelLimitOrder.js"; import { registerBinanceGetConvertTradeHistory } from "./getConvertTradeHistory.js"; @@ -9,24 +10,24 @@ import { registerBinanceConvertQueryLimitOpenOrders } from "./queryLimitOpenOrde import { registerBinanceConvertSendQuoteRequest } from "./sendQuoteRequest.js"; export function registerBinanceConvertTradeTools(server: McpServer) { - // Register the route to accept a quote for a convert trade - registerBinanceConvertAcceptQuote(server); + // Register the route to accept a quote for a convert trade + registerBinanceConvertAcceptQuote(server); - // Register the route to cancel an existing convert limit order - registerBinanceConvertCancelLimitOrder(server); + // Register the route to cancel an existing convert limit order + registerBinanceConvertCancelLimitOrder(server); - // Register the route to get the convert trade history - registerBinanceGetConvertTradeHistory(server); + // Register the route to get the convert trade history + registerBinanceGetConvertTradeHistory(server); - // Register the route to check the status of a convert order - registerBinanceConvertOrderStatus(server); + // Register the route to check the status of a convert order + registerBinanceConvertOrderStatus(server); - // Register the route to place a new convert limit order - registerBinanceConvertPlaceLimitOrder(server); + // Register the route to place a new convert limit order + registerBinanceConvertPlaceLimitOrder(server); - // Register the route to query currently open convert limit orders - registerBinanceConvertQueryLimitOpenOrders(server); + // Register the route to query currently open convert limit orders + registerBinanceConvertQueryLimitOpenOrders(server); - // Register the route to send a quote request for a convert trade - registerBinanceConvertSendQuoteRequest(server); + // Register the route to send a quote request for a convert trade + registerBinanceConvertSendQuoteRequest(server); } diff --git a/src/tools/binance-convert/trade-api/orderStatus.ts b/src/tools/binance-convert/trade-api/orderStatus.ts index 72d4b323..32ee7073 100644 --- a/src/tools/binance-convert/trade-api/orderStatus.ts +++ b/src/tools/binance-convert/trade-api/orderStatus.ts @@ -1,47 +1,53 @@ // src/tools/binance-convert/trade-api/orderStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertOrderStatus(server: McpServer) { - server.tool( - "BinanceConvertOrderStatus", + server.registerTool( + "BinanceConvertOrderStatus", + { + description: "The API checks the status of a token conversion order using either the orderId or quoteId, and returns details like conversion status, assets involved, amounts, exchange rate, and order creation time.", - { - orderId: z.string().optional().describe("Order ID (either this or quoteId is required)"), - quoteId: z.string().optional().describe("Quote ID (either this or orderId is required)") - }, - async (params) => { - try { - const response = await convertClient.restAPI.orderStatus({ - ...(params.orderId && { orderId: params.orderId }), - ...(params.quoteId && { quoteId: params.quoteId }) - }); + inputSchema: { + orderId: z.string().optional().describe("Order ID (either this or quoteId is required)"), + quoteId: z.string().optional().describe("Quote ID (either this or orderId is required)"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.orderStatus({ + ...(params.orderId && { orderId: params.orderId }), + ...(params.quoteId && { quoteId: params.quoteId }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully get the status of a token conversion . Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully get the status of a token conversion . Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to check the status: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to check the status: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/placeLimitOrder.ts b/src/tools/binance-convert/trade-api/placeLimitOrder.ts index 42fb17f1..2639e773 100644 --- a/src/tools/binance-convert/trade-api/placeLimitOrder.ts +++ b/src/tools/binance-convert/trade-api/placeLimitOrder.ts @@ -1,77 +1,86 @@ // src/tools/binance-convert/trade-api/placeLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertPlaceLimitOrder(server: McpServer) { - server.tool( - "BinanceConvertPlaceLimitOrder", + server.registerTool( + "BinanceConvertPlaceLimitOrder", + { + description: "Places a limit order to convert between two tokens at a specified price, using either base or quote amount, with options for wallet type and order expiry.", - { - baseAsset: z.string().describe("Base asset (from `fromIsBase` in /exchangeInfo API)"), - quoteAsset: z.string().describe("Quote asset"), - limitPrice: z.number().positive().describe("Symbol limit price (from baseAsset to quoteAsset)"), - baseAmount: z - .number() - .positive() - .optional() - .describe("Base asset amount (either this or quoteAmount is required)"), - quoteAmount: z - .number() - .positive() - .optional() - .describe("Quote asset amount (either this or baseAmount is required)"), - side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), - walletType: z - .enum(["SPOT", "FUNDING", "SPOT_FUNDING"]) - .optional() - .describe("Type of assets used: SPOT, FUNDING, or SPOT_FUNDING. Default is SPOT"), - expiredType: z - .enum(["1_D", "3_D", "7_D", "30_D"]) - .describe("Expiration type: 1_D, 3_D, 7_D, or 30_D (D = days)"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Time window for request validity") - }, - async (params) => { - try { - const response = await convertClient.restAPI.placeLimitOrder({ - baseAsset: params.baseAsset, - quoteAsset: params.quoteAsset, - limitPrice: params.limitPrice, - side: params.side, - expiredType: params.expiredType, - ...(params.baseAmount !== undefined && { baseAmount: params.baseAmount }), - ...(params.quoteAmount !== undefined && { quoteAmount: params.quoteAmount }), - ...(params.walletType && { walletType: params.walletType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + baseAsset: z.string().describe("Base asset (from `fromIsBase` in /exchangeInfo API)"), + quoteAsset: z.string().describe("Quote asset"), + limitPrice: z + .number() + .positive() + .describe("Symbol limit price (from baseAsset to quoteAsset)"), + baseAmount: z + .number() + .positive() + .optional() + .describe("Base asset amount (either this or quoteAmount is required)"), + quoteAmount: z + .number() + .positive() + .optional() + .describe("Quote asset amount (either this or baseAmount is required)"), + side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), + walletType: z + .enum(["SPOT", "FUNDING", "SPOT_FUNDING"]) + .optional() + .describe("Type of assets used: SPOT, FUNDING, or SPOT_FUNDING. Default is SPOT"), + expiredType: z + .enum(["1_D", "3_D", "7_D", "30_D"]) + .describe("Expiration type: 1_D, 3_D, 7_D, or 30_D (D = days)"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.placeLimitOrder({ + baseAsset: params.baseAsset, + quoteAsset: params.quoteAsset, + limitPrice: params.limitPrice, + side: params.side, + expiredType: params.expiredType, + ...(params.baseAmount !== undefined && { baseAmount: params.baseAmount }), + ...(params.quoteAmount !== undefined && { quoteAmount: params.quoteAmount }), + ...(params.walletType && { walletType: params.walletType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully placed the limit order. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully placed the limit order. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to places a limit order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to places a limit order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts b/src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts index c397279c..d96ede06 100644 --- a/src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts +++ b/src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts @@ -1,50 +1,56 @@ // src/tools/binance-convert/trade-api/queryLimitOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertQueryLimitOpenOrders(server: McpServer) { - server.tool( - "BinanceConvertQueryLimitOpenOrders", + server.registerTool( + "BinanceConvertQueryLimitOpenOrders", + { + description: "Retrieves all your open limit orders for token conversions, showing details like assets, amounts, exchange rate, order status, and expiration time.", - { - recvWindow: z - .number() - .int() - .max(60000, "recvWindow must not be greater than 60000") - .optional() - .describe("This value must not exceed 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.queryLimitOpenOrders({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000, "recvWindow must not be greater than 60000") + .optional() + .describe("This value must not exceed 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.queryLimitOpenOrders({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved all the open limit orders for token conversions. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved all the open limit orders for token conversions. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve all your open limit orders : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve all your open limit orders : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-convert/trade-api/sendQuoteRequest.ts b/src/tools/binance-convert/trade-api/sendQuoteRequest.ts index d3594f0c..c564cdc3 100644 --- a/src/tools/binance-convert/trade-api/sendQuoteRequest.ts +++ b/src/tools/binance-convert/trade-api/sendQuoteRequest.ts @@ -1,65 +1,82 @@ // src/tools/binance-convert/trade-api/sendQuoteRequest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { convertClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { convertClient } from "../../../config/binanceClient.js"; + export function registerBinanceConvertSendQuoteRequest(server: McpServer) { - server.tool( - "BinanceConvertSendQuoteRequest", + server.registerTool( + "BinanceConvertSendQuoteRequest", + { + description: "Get a real-time quote to convert one token to another, including rate and amount, if you have enough funds.", - { - fromAsset: z.string().describe("Asset you will spend (required)"), - toAsset: z.string().describe("Asset you will receive (required)"), - fromAmount: z.number().positive().optional().describe("Amount to be debited after conversion"), - toAmount: z.number().positive().optional().describe("Amount to be credited after conversion"), - walletType: z.enum(["SPOT", "FUNDING"]).optional().describe("SPOT or FUNDING. Default is SPOT"), - validTime: z - .enum(["10s", "30s", "1m"]) - .optional() - .describe("Quote validity duration: 10s, 30s, 1m; default is 10s"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const response = await convertClient.restAPI.sendQuoteRequest({ - fromAsset: params.fromAsset, - toAsset: params.toAsset, - ...(params.fromAmount && { fromAmount: params.fromAmount }), - ...(params.toAmount && { toAmount: params.toAmount }), - ...(params.walletType && { walletType: params.walletType }), - ...(params.validTime && { validTime: params.validTime }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + fromAsset: z.string().describe("Asset you will spend (required)"), + toAsset: z.string().describe("Asset you will receive (required)"), + fromAmount: z + .number() + .positive() + .optional() + .describe("Amount to be debited after conversion"), + toAmount: z + .number() + .positive() + .optional() + .describe("Amount to be credited after conversion"), + walletType: z + .enum(["SPOT", "FUNDING"]) + .optional() + .describe("SPOT or FUNDING. Default is SPOT"), + validTime: z + .enum(["10s", "30s", "1m"]) + .optional() + .describe("Quote validity duration: 10s, 30s, 1m; default is 10s"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await convertClient.restAPI.sendQuoteRequest({ + fromAsset: params.fromAsset, + toAsset: params.toAsset, + ...(params.fromAmount && { fromAmount: params.fromAmount }), + ...(params.toAmount && { toAmount: params.toAmount }), + ...(params.walletType && { walletType: params.walletType }), + ...(params.validTime && { validTime: params.validTime }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved real-time quote to convert one token to another. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved real-time quote to convert one token to another. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to get a real-time quote to convert: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to get a real-time quote to convert: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/followTrader.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/followTrader.ts index f219f523..a6fae0f4 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/followTrader.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/followTrader.ts @@ -1,52 +1,68 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/followTrader.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingFollow(server: McpServer) { - server.tool( - "BinanceCopyTradingFollow", + server.registerTool( + "BinanceCopyTradingFollow", + { + description: "Start following a lead trader in copy trading. ⚠️ WARNING: This will automatically copy their trades. You are trusting another trader with your capital. Past performance does not guarantee future results.", - { - portfolioId: z.string() - .describe("Lead trader's portfolio ID to follow"), - copyRatio: z.number().min(0.1).max(10).optional() - .describe("Copy ratio multiplier (0.1-10x, default 1x)"), - stopLossRatio: z.number().min(0.01).max(1).optional() - .describe("Stop loss ratio (e.g., 0.1 = 10% loss triggers stop)"), - takeProfitRatio: z.number().min(0.01).optional() - .describe("Take profit ratio (e.g., 0.5 = 50% profit triggers exit)"), - fixedAmount: z.string().optional() - .describe("Fixed amount per trade instead of ratio"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.followLeadTrader({ - portfolioId: params.portfolioId, - ...(params.copyRatio && { copyRatio: params.copyRatio }), - ...(params.stopLossRatio && { stopLossRatio: params.stopLossRatio }), - ...(params.takeProfitRatio && { takeProfitRatio: params.takeProfitRatio }), - ...(params.fixedAmount && { fixedAmount: params.fixedAmount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + portfolioId: z.string().describe("Lead trader's portfolio ID to follow"), + copyRatio: z + .number() + .min(0.1) + .max(10) + .optional() + .describe("Copy ratio multiplier (0.1-10x, default 1x)"), + stopLossRatio: z + .number() + .min(0.01) + .max(1) + .optional() + .describe("Stop loss ratio (e.g., 0.1 = 10% loss triggers stop)"), + takeProfitRatio: z + .number() + .min(0.01) + .optional() + .describe("Take profit ratio (e.g., 0.5 = 50% profit triggers exit)"), + fixedAmount: z.string().optional().describe("Fixed amount per trade instead of ratio"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.followLeadTrader({ + portfolioId: params.portfolioId, + ...(params.copyRatio && { copyRatio: params.copyRatio }), + ...(params.stopLossRatio && { stopLossRatio: params.stopLossRatio }), + ...(params.takeProfitRatio && { takeProfitRatio: params.takeProfitRatio }), + ...(params.fixedAmount && { fixedAmount: params.fixedAmount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Now following trader ${params.portfolioId}!\n\nCopy Ratio: ${params.copyRatio || 1}x\nStop Loss: ${params.stopLossRatio ? params.stopLossRatio * 100 + "%" : "Not set"}\nTake Profit: ${params.takeProfitRatio ? params.takeProfitRatio * 100 + "%" : "Not set"}\n\n⚠️ Monitor your positions regularly.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Now following trader ${params.portfolioId}!\n\nCopy Ratio: ${params.copyRatio || 1}x\nStop Loss: ${params.stopLossRatio ? (params.stopLossRatio * 100) + '%' : 'Not set'}\nTake Profit: ${params.takeProfitRatio ? (params.takeProfitRatio * 100) + '%' : 'Not set'}\n\n⚠️ Monitor your positions regularly.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to follow trader: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to follow trader: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyOrders.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyOrders.ts index 1e2c07fe..6f769b0a 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyOrders.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyOrders.ts @@ -1,55 +1,56 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetOrders(server: McpServer) { - server.tool( - "BinanceCopyTradingGetOrders", + server.registerTool( + "BinanceCopyTradingGetOrders", + { + description: "Get copy trading orders. Shows orders that were placed as a result of following lead traders.", - { - portfolioId: z.string().optional() - .describe("Filter by specific lead trader portfolio ID"), - symbol: z.string().optional() - .describe("Filter by trading symbol"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - pageNumber: z.number().int().min(1).optional() - .describe("Page number"), - pageSize: z.number().int().min(1).max(100).optional() - .describe("Results per page"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getCopyTradingOrders({ - ...(params.portfolioId && { portfolioId: params.portfolioId }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.pageNumber && { pageNumber: params.pageNumber }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + portfolioId: z.string().optional().describe("Filter by specific lead trader portfolio ID"), + symbol: z.string().optional().describe("Filter by trading symbol"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + pageNumber: z.number().int().min(1).optional().describe("Page number"), + pageSize: z.number().int().min(1).max(100).optional().describe("Results per page"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getCopyTradingOrders({ + ...(params.portfolioId && { portfolioId: params.portfolioId }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.pageNumber && { pageNumber: params.pageNumber }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Copy Trading Orders:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Copy Trading Orders:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get copy orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get copy orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyPositions.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyPositions.ts index 0bfc1ca5..33f9deda 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyPositions.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyPositions.ts @@ -1,43 +1,48 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getCopyPositions.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetPositions(server: McpServer) { - server.tool( - "BinanceCopyTradingGetPositions", + server.registerTool( + "BinanceCopyTradingGetPositions", + { + description: "Get current copy trading positions. Shows open positions from following lead traders.", - { - portfolioId: z.string().optional() - .describe("Filter by specific lead trader portfolio ID"), - symbol: z.string().optional() - .describe("Filter by trading symbol"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getCopyTradingPositions({ - ...(params.portfolioId && { portfolioId: params.portfolioId }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + portfolioId: z.string().optional().describe("Filter by specific lead trader portfolio ID"), + symbol: z.string().optional().describe("Filter by trading symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getCopyTradingPositions({ + ...(params.portfolioId && { portfolioId: params.portfolioId }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Copy Trading Positions:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Copy Trading Positions:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get copy positions: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get copy positions: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFollowingTraders.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFollowingTraders.ts index bd9504a2..8697a59d 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFollowingTraders.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFollowingTraders.ts @@ -1,37 +1,43 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getFollowingTraders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetFollowing(server: McpServer) { - server.tool( - "BinanceCopyTradingGetFollowing", - "Get list of traders you are currently following in copy trading.", - { - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFollowingTraders({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCopyTradingGetFollowing", + { + description: "Get list of traders you are currently following in copy trading.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getFollowingTraders({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Traders You're Following:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Traders You're Following:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get following traders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get following traders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts index def3b5f3..5c58fabe 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts @@ -1,45 +1,55 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTraderStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFuturesLeadTraderStatus(server: McpServer) { - server.tool( - "BinanceGetFuturesLeadTraderStatus", + server.registerTool( + "BinanceGetFuturesLeadTraderStatus", + { + description: "Checks and returns whether the user is currently a Futures Lead Trader in Binance Copy Trading, along with the timestamp of the status check.", - { - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFuturesLeadTraderStatus({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getFuturesLeadTraderStatus({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved user futures trading details. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved user futures trading details. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to Check and return whether the user is currently a Futures Lead Trader in Binance Copy Trading: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to Check and return whether the user is currently a Futures Lead Trader in Binance Copy Trading: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts index 09399375..9c9be5f6 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts @@ -1,43 +1,55 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getFuturesLeadTradingSymbolWhitelist.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFuturesLeadTradingSymbolWhitelist(server: McpServer) { - server.tool( - "BinanceGetFuturesLeadTradingSymbolWhitelist", + server.registerTool( + "BinanceGetFuturesLeadTradingSymbolWhitelist", + { + description: "Whitelist of trading pairs (symbols) that are allowed for Futures Lead Traders in copy trading, including base and quote assets.", - { - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getFuturesLeadTradingSymbolWhitelist({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await ( + copyTradingClient as any + ).restAPI.getFuturesLeadTradingSymbolWhitelist({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved trading pairs. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved trading pairs. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to whitelist of trading pairs: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to whitelist of trading pairs: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getLeadTraders.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getLeadTraders.ts index 97848a5e..d2f9b498 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getLeadTraders.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getLeadTraders.ts @@ -5,45 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-copy-trading/FutureCopyTrading-api/getLeadTraders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetLeaders(server: McpServer) { - server.tool( - "BinanceCopyTradingGetLeaders", + server.registerTool( + "BinanceCopyTradingGetLeaders", + { + description: "Get a list of lead traders available for copy trading. Shows their performance metrics and follower count.", - { - pageNumber: z.number().int().min(1).optional() - .describe("Page number for pagination"), - pageSize: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getLeadTraders({ - ...(params.pageNumber && { pageNumber: params.pageNumber }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + pageNumber: z.number().int().min(1).optional().describe("Page number for pagination"), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getLeadTraders({ + ...(params.pageNumber && { pageNumber: params.pageNumber }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Lead Traders:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Lead Traders:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get lead traders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get lead traders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/getTraderPerformance.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/getTraderPerformance.ts index 9fc35e1b..3f5c18f3 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/getTraderPerformance.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/getTraderPerformance.ts @@ -1,40 +1,46 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/getTraderPerformance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingGetPerformance(server: McpServer) { - server.tool( - "BinanceCopyTradingGetPerformance", + server.registerTool( + "BinanceCopyTradingGetPerformance", + { + description: "Get detailed performance statistics for a specific lead trader. Includes ROI, win rate, PnL history.", - { - portfolioId: z.string() - .describe("Lead trader's portfolio ID"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.getLeadTraderPerformance({ - portfolioId: params.portfolioId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + portfolioId: z.string().describe("Lead trader's portfolio ID"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.getLeadTraderPerformance({ + portfolioId: params.portfolioId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Trader Performance for ${params.portfolioId}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Trader Performance for ${params.portfolioId}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get trader performance: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get trader performance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts index 486470c3..27f03171 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFuturesLeadTraderStatus } from "./getFuturesLeadTraderStatus.js"; import { registerBinanceGetFuturesLeadTradingSymbolWhitelist } from "./getFuturesLeadTradingSymbolWhitelist.js"; // Registers Binance Futures Copy Trading API tools with the MCP server. export function registerBinanceFutureCopyTradingApiTools(server: McpServer) { - // Registers an endpoint to get the status of a lead trader in futures copy trading - registerBinanceGetFuturesLeadTraderStatus(server); + // Registers an endpoint to get the status of a lead trader in futures copy trading + registerBinanceGetFuturesLeadTraderStatus(server); - // Registers an endpoint to get the whitelist of symbols available for futures copy trading - registerBinanceGetFuturesLeadTradingSymbolWhitelist(server); + // Registers an endpoint to get the whitelist of symbols available for futures copy trading + registerBinanceGetFuturesLeadTradingSymbolWhitelist(server); } diff --git a/src/tools/binance-copy-trading/FutureCopyTrading-api/unfollowTrader.ts b/src/tools/binance-copy-trading/FutureCopyTrading-api/unfollowTrader.ts index 08772d08..2aa1e164 100644 --- a/src/tools/binance-copy-trading/FutureCopyTrading-api/unfollowTrader.ts +++ b/src/tools/binance-copy-trading/FutureCopyTrading-api/unfollowTrader.ts @@ -1,40 +1,46 @@ // src/tools/binance-copy-trading/FutureCopyTrading-api/unfollowTrader.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { copyTradingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { copyTradingClient } from "../../../config/binanceClient.js"; + export function registerBinanceCopyTradingUnfollow(server: McpServer) { - server.tool( - "BinanceCopyTradingUnfollow", + server.registerTool( + "BinanceCopyTradingUnfollow", + { + description: "Stop following a lead trader. This will stop copying their trades but won't close existing positions.", - { - portfolioId: z.string() - .describe("Lead trader's portfolio ID to unfollow"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await copyTradingClient.restAPI.unfollowLeadTrader({ - portfolioId: params.portfolioId, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + portfolioId: z.string().describe("Lead trader's portfolio ID to unfollow"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (copyTradingClient as any).restAPI.unfollowLeadTrader({ + portfolioId: params.portfolioId, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Stopped following trader ${params.portfolioId}\n\n📝 Note: Existing copied positions remain open. Close them manually if needed.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Stopped following trader ${params.portfolioId}\n\n📝 Note: Existing copied positions remain open. Close them manually if needed.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to unfollow trader: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to unfollow trader: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-copy-trading/index.ts b/src/tools/binance-copy-trading/index.ts index cf3b9ae0..4dabc39b 100644 --- a/src/tools/binance-copy-trading/index.ts +++ b/src/tools/binance-copy-trading/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-copy-trading/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFutureCopyTradingApiTools } from "./FutureCopyTrading-api/index.js"; // Registers all Binance Copy Trading related tools with the MCP server. export function registerBinanceCopyTradingTools(server: McpServer) { - // Register the Binance Futures Copy Trading API tools with the given server. - registerBinanceFutureCopyTradingApiTools(server); + // Register the Binance Futures Copy Trading API tools with the given server. + registerBinanceFutureCopyTradingApiTools(server); } diff --git a/src/tools/binance-crypto-loans/fixed-api/adjustLTV.ts b/src/tools/binance-crypto-loans/fixed-api/adjustLTV.ts index 433a090e..e9ed28fd 100644 --- a/src/tools/binance-crypto-loans/fixed-api/adjustLTV.ts +++ b/src/tools/binance-crypto-loans/fixed-api/adjustLTV.ts @@ -5,49 +5,55 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/adjustLTV.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedAdjustLTV(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedAdjustLTV", - "Adjust LTV for a fixed-term loan by adding or removing collateral.", - { - orderId: z.number().int() - .describe("Loan order ID"), - amount: z.string() - .describe("Amount of collateral to add or remove"), - direction: z.enum(["ADDITIONAL", "REDUCED"]) - .describe("Direction: ADDITIONAL to add collateral, REDUCED to remove"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.cryptoLoanAdjustLtv({ - orderId: params.orderId, - amount: params.amount, - direction: params.direction, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoansFixedAdjustLTV", + { + description: "Adjust LTV for a fixed-term loan by adding or removing collateral.", + inputSchema: { + orderId: z.number().int().describe("Loan order ID"), + amount: z.string().describe("Amount of collateral to add or remove"), + direction: z + .enum(["ADDITIONAL", "REDUCED"]) + .describe("Direction: ADDITIONAL to add collateral, REDUCED to remove"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.cryptoLoanAdjustLtv({ + orderId: params.orderId, + amount: params.amount, + direction: params.direction, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const action = params.direction === "ADDITIONAL" ? "added" : "removed"; - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ LTV Adjusted!\n\nOrder ID: ${params.orderId}\nCollateral ${action}: ${params.amount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const action = params.direction === "ADDITIONAL" ? "added" : "removed"; - return { - content: [{ - type: "text", - text: `✅ LTV Adjusted!\n\nOrder ID: ${params.orderId}\nCollateral ${action}: ${params.amount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to adjust LTV: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to adjust LTV: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/borrow.ts b/src/tools/binance-crypto-loans/fixed-api/borrow.ts index 45ffa855..aa16b9a0 100644 --- a/src/tools/binance-crypto-loans/fixed-api/borrow.ts +++ b/src/tools/binance-crypto-loans/fixed-api/borrow.ts @@ -5,61 +5,71 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/borrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedBorrow(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedBorrow", + server.registerTool( + "BinanceCryptoLoansFixedBorrow", + { + description: "Borrow crypto using a fixed-term loan. ⚠️ WARNING: Fixed loans have a specific term. Your collateral is locked until repayment. Failure to repay may result in liquidation.", - { - loanCoin: z.string() - .describe("Coin to borrow (e.g., 'USDT')"), - collateralCoin: z.string() - .describe("Collateral coin (e.g., 'BTC')"), - loanTerm: z.number().int() - .describe("Loan term in days (7, 14, 30, 90, 180)"), - loanAmount: z.string().optional() - .describe("Amount to borrow (provide either loanAmount or collateralAmount)"), - collateralAmount: z.string().optional() - .describe("Collateral amount (provide either loanAmount or collateralAmount)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - if (!params.loanAmount && !params.collateralAmount) { - return { - content: [{ type: "text", text: "❌ Either loanAmount or collateralAmount must be provided" }], - isError: true - }; - } + inputSchema: { + loanCoin: z.string().describe("Coin to borrow (e.g., 'USDT')"), + collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC')"), + loanTerm: z.number().int().describe("Loan term in days (7, 14, 30, 90, 180)"), + loanAmount: z + .string() + .optional() + .describe("Amount to borrow (provide either loanAmount or collateralAmount)"), + collateralAmount: z + .string() + .optional() + .describe("Collateral amount (provide either loanAmount or collateralAmount)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + if (!params.loanAmount && !params.collateralAmount) { + return { + content: [ + { type: "text", text: "❌ Either loanAmount or collateralAmount must be provided" }, + ], + isError: true, + }; + } - const response = await cryptoLoanClient.restAPI.cryptoLoanBorrow({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - loanTerm: params.loanTerm, - ...(params.loanAmount && { loanAmount: params.loanAmount }), - ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + const response = await (cryptoLoanClient as any).restAPI.cryptoLoanBorrow({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + loanTerm: params.loanTerm, + ...(params.loanAmount && { loanAmount: params.loanAmount }), + ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); - const data = await response.data(); + const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Fixed-Term Loan Created!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\nTerm: ${params.loanTerm} days\n\n⚠️ Remember to repay before the term ends to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to borrow: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `✅ Fixed-Term Loan Created!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\nTerm: ${params.loanTerm} days\n\n⚠️ Remember to repay before the term ends to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to borrow: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/checkCollateralRate.ts b/src/tools/binance-crypto-loans/fixed-api/checkCollateralRate.ts index 5a36932c..4969bbff 100644 --- a/src/tools/binance-crypto-loans/fixed-api/checkCollateralRate.ts +++ b/src/tools/binance-crypto-loans/fixed-api/checkCollateralRate.ts @@ -5,48 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/checkCollateralRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedCollateralRate(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedCollateralRate", + server.registerTool( + "BinanceCryptoLoansFixedCollateralRate", + { + description: "Check the collateral repay rate for a specific loan and collateral pair. Useful for planning repayments.", - { - loanCoin: z.string() - .describe("Loan coin (e.g., 'USDT')"), - collateralCoin: z.string() - .describe("Collateral coin (e.g., 'BTC')"), - repayAmount: z.string() - .describe("Amount to repay"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.checkCollateralRepayRate({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - repayAmount: params.repayAmount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., 'USDT')"), + collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC')"), + repayAmount: z.string().describe("Amount to repay"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.checkCollateralRepayRate({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + repayAmount: params.repayAmount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Collateral Repay Rate:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Collateral Repay Rate:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to check collateral rate: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to check collateral rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/customizeMarginCall.ts b/src/tools/binance-crypto-loans/fixed-api/customizeMarginCall.ts index 3fb13426..57fb64c4 100644 --- a/src/tools/binance-crypto-loans/fixed-api/customizeMarginCall.ts +++ b/src/tools/binance-crypto-loans/fixed-api/customizeMarginCall.ts @@ -5,45 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/customizeMarginCall.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedMarginCall(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedMarginCall", + server.registerTool( + "BinanceCryptoLoansFixedMarginCall", + { + description: "Customize margin call threshold for a loan. Set when you want to be notified about LTV changes.", - { - orderId: z.number().int() - .describe("Loan order ID"), - marginCall: z.number() - .describe("Margin call LTV threshold (e.g., 0.8 for 80%)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.customizeMarginCall({ - orderId: params.orderId, - marginCall: params.marginCall, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().describe("Loan order ID"), + marginCall: z.number().describe("Margin call LTV threshold (e.g., 0.8 for 80%)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.customizeMarginCall({ + orderId: params.orderId, + marginCall: params.marginCall, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Margin call threshold updated!\n\nOrder ID: ${params.orderId}\nNew Threshold: ${params.marginCall * 100}%\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Margin call threshold updated!\n\nOrder ID: ${params.orderId}\nNew Threshold: ${params.marginCall * 100}%\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to customize margin call: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to customize margin call: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/getBorrowHistory.ts b/src/tools/binance-crypto-loans/fixed-api/getBorrowHistory.ts index d044955e..fa7eb4fe 100644 --- a/src/tools/binance-crypto-loans/fixed-api/getBorrowHistory.ts +++ b/src/tools/binance-crypto-loans/fixed-api/getBorrowHistory.ts @@ -5,60 +5,59 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/getBorrowHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedBorrowHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedBorrowHistory", - "Get borrow history for fixed-term loans.", - { - orderId: z.number().int().optional() - .describe("Filter by specific order ID"), - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - current: z.number().int().min(1).optional() - .describe("Current page"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getLoanBorrowHistory({ - ...(params.orderId && { orderId: params.orderId }), - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoansFixedBorrowHistory", + { + description: "Get borrow history for fixed-term loans.", + inputSchema: { + orderId: z.number().int().optional().describe("Filter by specific order ID"), + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().min(1).optional().describe("Current page"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getLoanBorrowHistory({ + ...(params.orderId && { orderId: params.orderId }), + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Fixed Loan Borrow History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Fixed Loan Borrow History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get borrow history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get borrow history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/getFixedCollateralData.ts b/src/tools/binance-crypto-loans/fixed-api/getFixedCollateralData.ts index 077cfb40..1a7b973b 100644 --- a/src/tools/binance-crypto-loans/fixed-api/getFixedCollateralData.ts +++ b/src/tools/binance-crypto-loans/fixed-api/getFixedCollateralData.ts @@ -5,45 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/getFixedCollateralData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedCollateral(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedCollateral", + server.registerTool( + "BinanceCryptoLoansFixedCollateral", + { + description: "Get list of collateral assets for fixed-term loans. Shows LTV ratios and limits.", - { - collateralCoin: z.string().optional() - .describe("Filter by specific collateral coin"), - vipLevel: z.number().int().min(0).max(9).optional() - .describe("VIP level"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getCollateralAssetsData({ - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + collateralCoin: z.string().optional().describe("Filter by specific collateral coin"), + vipLevel: z.number().int().min(0).max(9).optional().describe("VIP level"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getCollateralAssetsData({ + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Fixed Loan Collateral Assets:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Fixed Loan Collateral Assets:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get collateral data: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get collateral data: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/getFixedLoanData.ts b/src/tools/binance-crypto-loans/fixed-api/getFixedLoanData.ts index 5fb61d72..646ba23c 100644 --- a/src/tools/binance-crypto-loans/fixed-api/getFixedLoanData.ts +++ b/src/tools/binance-crypto-loans/fixed-api/getFixedLoanData.ts @@ -5,45 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/getFixedLoanData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedAssets", + server.registerTool( + "BinanceCryptoLoansFixedAssets", + { + description: "Get list of assets available for fixed-term crypto loans. Shows borrowable assets with interest rates, terms, and limits.", - { - loanCoin: z.string().optional() - .describe("Filter by specific loan coin"), - vipLevel: z.number().int().min(0).max(9).optional() - .describe("VIP level for rate calculation"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getLoanableAssetsData({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by specific loan coin"), + vipLevel: z + .number() + .int() + .min(0) + .max(9) + .optional() + .describe("VIP level for rate calculation"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getLoanableAssetsData({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Fixed Loan Assets:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Fixed Loan Assets:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get fixed loan assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get fixed loan assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/getOngoingOrders.ts b/src/tools/binance-crypto-loans/fixed-api/getOngoingOrders.ts index edec9a94..df654fe2 100644 --- a/src/tools/binance-crypto-loans/fixed-api/getOngoingOrders.ts +++ b/src/tools/binance-crypto-loans/fixed-api/getOngoingOrders.ts @@ -5,54 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/getOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedOngoing(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedOngoing", + server.registerTool( + "BinanceCryptoLoansFixedOngoing", + { + description: "Get ongoing fixed-term loan orders. Shows current loans with term, principal, interest, and LTV.", - { - orderId: z.number().int().optional() - .describe("Filter by specific order ID"), - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - current: z.number().int().min(1).optional() - .describe("Current page"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getLoanOngoingOrders({ - ...(params.orderId && { orderId: params.orderId }), - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().optional().describe("Filter by specific order ID"), + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + current: z.number().int().min(1).optional().describe("Current page"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getLoanOngoingOrders({ + ...(params.orderId && { orderId: params.orderId }), + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Ongoing Fixed Loans:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Ongoing Fixed Loans:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get ongoing orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get ongoing orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/getRepayHistory.ts b/src/tools/binance-crypto-loans/fixed-api/getRepayHistory.ts index fe6b17c4..dd6bc5d1 100644 --- a/src/tools/binance-crypto-loans/fixed-api/getRepayHistory.ts +++ b/src/tools/binance-crypto-loans/fixed-api/getRepayHistory.ts @@ -5,60 +5,59 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/getRepayHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedRepayHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedRepayHistory", - "Get repayment history for fixed-term loans.", - { - orderId: z.number().int().optional() - .describe("Filter by specific order ID"), - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - current: z.number().int().min(1).optional() - .describe("Current page"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getLoanRepaymentHistory({ - ...(params.orderId && { orderId: params.orderId }), - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoansFixedRepayHistory", + { + description: "Get repayment history for fixed-term loans.", + inputSchema: { + orderId: z.number().int().optional().describe("Filter by specific order ID"), + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().min(1).optional().describe("Current page"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getLoanRepaymentHistory({ + ...(params.orderId && { orderId: params.orderId }), + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Fixed Loan Repay History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Fixed Loan Repay History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get repay history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get repay history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/fixed-api/index.ts b/src/tools/binance-crypto-loans/fixed-api/index.ts index 25b7c7d9..f8a542f6 100644 --- a/src/tools/binance-crypto-loans/fixed-api/index.ts +++ b/src/tools/binance-crypto-loans/fixed-api/index.ts @@ -5,27 +5,28 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceCryptoLoansFixedAssets } from "./getFixedLoanData.js"; -import { registerBinanceCryptoLoansFixedCollateral } from "./getFixedCollateralData.js"; -import { registerBinanceCryptoLoansFixedBorrow } from "./borrow.js"; -import { registerBinanceCryptoLoansFixedRepay } from "./repay.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCryptoLoansFixedAdjustLTV } from "./adjustLTV.js"; -import { registerBinanceCryptoLoansFixedOngoing } from "./getOngoingOrders.js"; -import { registerBinanceCryptoLoansFixedBorrowHistory } from "./getBorrowHistory.js"; -import { registerBinanceCryptoLoansFixedRepayHistory } from "./getRepayHistory.js"; +import { registerBinanceCryptoLoansFixedBorrow } from "./borrow.js"; import { registerBinanceCryptoLoansFixedCollateralRate } from "./checkCollateralRate.js"; import { registerBinanceCryptoLoansFixedMarginCall } from "./customizeMarginCall.js"; +import { registerBinanceCryptoLoansFixedBorrowHistory } from "./getBorrowHistory.js"; +import { registerBinanceCryptoLoansFixedCollateral } from "./getFixedCollateralData.js"; +import { registerBinanceCryptoLoansFixedAssets } from "./getFixedLoanData.js"; +import { registerBinanceCryptoLoansFixedOngoing } from "./getOngoingOrders.js"; +import { registerBinanceCryptoLoansFixedRepayHistory } from "./getRepayHistory.js"; +import { registerBinanceCryptoLoansFixedRepay } from "./repay.js"; export function registerBinanceCryptoLoansFixedTools(server: McpServer) { - registerBinanceCryptoLoansFixedAssets(server); - registerBinanceCryptoLoansFixedCollateral(server); - registerBinanceCryptoLoansFixedCollateralRate(server); - registerBinanceCryptoLoansFixedMarginCall(server); - registerBinanceCryptoLoansFixedBorrow(server); - registerBinanceCryptoLoansFixedRepay(server); - registerBinanceCryptoLoansFixedAdjustLTV(server); - registerBinanceCryptoLoansFixedOngoing(server); - registerBinanceCryptoLoansFixedBorrowHistory(server); - registerBinanceCryptoLoansFixedRepayHistory(server); + registerBinanceCryptoLoansFixedAssets(server); + registerBinanceCryptoLoansFixedCollateral(server); + registerBinanceCryptoLoansFixedCollateralRate(server); + registerBinanceCryptoLoansFixedMarginCall(server); + registerBinanceCryptoLoansFixedBorrow(server); + registerBinanceCryptoLoansFixedRepay(server); + registerBinanceCryptoLoansFixedAdjustLTV(server); + registerBinanceCryptoLoansFixedOngoing(server); + registerBinanceCryptoLoansFixedBorrowHistory(server); + registerBinanceCryptoLoansFixedRepayHistory(server); } diff --git a/src/tools/binance-crypto-loans/fixed-api/repay.ts b/src/tools/binance-crypto-loans/fixed-api/repay.ts index ac5a88bf..23bf1003 100644 --- a/src/tools/binance-crypto-loans/fixed-api/repay.ts +++ b/src/tools/binance-crypto-loans/fixed-api/repay.ts @@ -5,51 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/fixed-api/repay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFixedRepay(server: McpServer) { - server.tool( - "BinanceCryptoLoansFixedRepay", - "Repay a fixed-term crypto loan. Repaying unlocks your collateral.", - { - orderId: z.number().int() - .describe("Loan order ID to repay"), - amount: z.string() - .describe("Amount to repay"), - type: z.enum(["1", "2"]).optional() - .describe("Repay type: 1 = repay with borrowed coin, 2 = repay with collateral"), - collateralReturn: z.boolean().optional() - .describe("Whether to return collateral after full repayment"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.cryptoLoanRepay({ - orderId: params.orderId, - amount: params.amount, - ...(params.type && { type: params.type }), - ...(params.collateralReturn !== undefined && { collateralReturn: params.collateralReturn }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCryptoLoansFixedRepay", + { + description: "Repay a fixed-term crypto loan. Repaying unlocks your collateral.", + inputSchema: { + orderId: z.number().int().describe("Loan order ID to repay"), + amount: z.string().describe("Amount to repay"), + type: z + .enum(["1", "2"]) + .optional() + .describe("Repay type: 1 = repay with borrowed coin, 2 = repay with collateral"), + collateralReturn: z + .boolean() + .optional() + .describe("Whether to return collateral after full repayment"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.cryptoLoanRepay({ + orderId: params.orderId, + amount: params.amount, + ...(params.type && { type: params.type }), + ...(params.collateralReturn !== undefined && { + collateralReturn: params.collateralReturn, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Loan Repayment Successful!\n\nOrder ID: ${params.orderId}\nAmount Repaid: ${params.amount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Loan Repayment Successful!\n\nOrder ID: ${params.orderId}\nAmount Repaid: ${params.amount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to repay loan: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to repay loan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/adjustLTV.ts b/src/tools/binance-crypto-loans/flexible-api/adjustLTV.ts index 693a5792..c638864a 100644 --- a/src/tools/binance-crypto-loans/flexible-api/adjustLTV.ts +++ b/src/tools/binance-crypto-loans/flexible-api/adjustLTV.ts @@ -5,52 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/adjustLTV.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleAdjustLTV(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleAdjustLTV", + server.registerTool( + "BinanceCryptoLoansFlexibleAdjustLTV", + { + description: "Adjust LTV (Loan-to-Value) ratio by adding or removing collateral. Lower LTV reduces liquidation risk.", - { - loanCoin: z.string() - .describe("Loan coin (e.g., 'USDT')"), - collateralCoin: z.string() - .describe("Collateral coin (e.g., 'BTC')"), - adjustmentAmount: z.string() - .describe("Amount of collateral to add or remove"), - direction: z.enum(["ADDITIONAL", "REDUCED"]) - .describe("Direction: ADDITIONAL to add collateral (lower LTV), REDUCED to remove collateral (higher LTV)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.flexibleLoanAdjustLtv({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - adjustmentAmount: params.adjustmentAmount, - direction: params.direction, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., 'USDT')"), + collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC')"), + adjustmentAmount: z.string().describe("Amount of collateral to add or remove"), + direction: z + .enum(["ADDITIONAL", "REDUCED"]) + .describe( + "Direction: ADDITIONAL to add collateral (lower LTV), REDUCED to remove collateral (higher LTV)", + ), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanAdjustLtv({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + adjustmentAmount: params.adjustmentAmount, + direction: params.direction, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const action = params.direction === "ADDITIONAL" ? "added" : "removed"; - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ LTV Adjusted!\n\nCollateral ${action}: ${params.adjustmentAmount} ${params.collateralCoin}\n\n${params.direction === "ADDITIONAL" ? "Your liquidation risk is now lower." : "⚠️ Your liquidation risk may have increased."}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const action = params.direction === "ADDITIONAL" ? "added" : "removed"; - return { - content: [{ - type: "text", - text: `✅ LTV Adjusted!\n\nCollateral ${action}: ${params.adjustmentAmount} ${params.collateralCoin}\n\n${params.direction === "ADDITIONAL" ? "Your liquidation risk is now lower." : "⚠️ Your liquidation risk may have increased."}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to adjust LTV: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to adjust LTV: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/borrow.ts b/src/tools/binance-crypto-loans/flexible-api/borrow.ts index ce3b5414..6ec6f609 100644 --- a/src/tools/binance-crypto-loans/flexible-api/borrow.ts +++ b/src/tools/binance-crypto-loans/flexible-api/borrow.ts @@ -5,59 +5,70 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/borrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleBorrow(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleBorrow", + server.registerTool( + "BinanceCryptoLoansFlexibleBorrow", + { + description: "Borrow crypto using a flexible loan. ⚠️ WARNING: Your collateral will be locked. Interest accrues daily. If LTV ratio exceeds threshold, liquidation may occur.", - { - loanCoin: z.string() - .describe("Coin to borrow (e.g., 'USDT', 'BUSD')"), - collateralCoin: z.string() - .describe("Collateral coin (e.g., 'BTC', 'ETH')"), - loanAmount: z.string().optional() - .describe("Amount to borrow (provide either loanAmount or collateralAmount)"), - collateralAmount: z.string().optional() - .describe("Collateral amount (provide either loanAmount or collateralAmount)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - // Validate that either loanAmount or collateralAmount is provided - if (!params.loanAmount && !params.collateralAmount) { - return { - content: [{ type: "text", text: "❌ Either loanAmount or collateralAmount must be provided" }], - isError: true - }; - } + inputSchema: { + loanCoin: z.string().describe("Coin to borrow (e.g., 'USDT', 'BUSD')"), + collateralCoin: z.string().describe("Collateral coin (e.g., 'BTC', 'ETH')"), + loanAmount: z + .string() + .optional() + .describe("Amount to borrow (provide either loanAmount or collateralAmount)"), + collateralAmount: z + .string() + .optional() + .describe("Collateral amount (provide either loanAmount or collateralAmount)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + // Validate that either loanAmount or collateralAmount is provided + if (!params.loanAmount && !params.collateralAmount) { + return { + content: [ + { type: "text", text: "❌ Either loanAmount or collateralAmount must be provided" }, + ], + isError: true, + }; + } - const response = await cryptoLoanClient.restAPI.flexibleLoanBorrow({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - ...(params.loanAmount && { loanAmount: params.loanAmount }), - ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanBorrow({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + ...(params.loanAmount && { loanAmount: params.loanAmount }), + ...(params.collateralAmount && { collateralAmount: params.collateralAmount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); - const data = await response.data(); + const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Flexible Loan Borrowed!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\n\n⚠️ Monitor your LTV ratio regularly to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to borrow: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `✅ Flexible Loan Borrowed!\n\nLoan Coin: ${params.loanCoin}\nCollateral: ${params.collateralCoin}\n\n⚠️ Monitor your LTV ratio regularly to avoid liquidation.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to borrow: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/getBorrowHistory.ts b/src/tools/binance-crypto-loans/flexible-api/getBorrowHistory.ts index 859079b1..28f507b8 100644 --- a/src/tools/binance-crypto-loans/flexible-api/getBorrowHistory.ts +++ b/src/tools/binance-crypto-loans/flexible-api/getBorrowHistory.ts @@ -5,57 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/getBorrowHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleBorrowHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleBorrowHistory", + server.registerTool( + "BinanceCryptoLoansFlexibleBorrowHistory", + { + description: "Get borrow history for flexible loans. Shows all past and current borrow transactions.", - { - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - current: z.number().int().min(1).optional() - .describe("Current page (default 1)"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanBorrowHistory({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().min(1).optional().describe("Current page (default 1)"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanBorrowHistory({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Flexible Loan Borrow History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Flexible Loan Borrow History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get borrow history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get borrow history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/getFlexibleCollateralAssets.ts b/src/tools/binance-crypto-loans/flexible-api/getFlexibleCollateralAssets.ts index f732678e..3ec506d7 100644 --- a/src/tools/binance-crypto-loans/flexible-api/getFlexibleCollateralAssets.ts +++ b/src/tools/binance-crypto-loans/flexible-api/getFlexibleCollateralAssets.ts @@ -5,42 +5,53 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/getFlexibleCollateralAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleCollateral(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleCollateral", + server.registerTool( + "BinanceCryptoLoansFlexibleCollateral", + { + description: "Get list of assets that can be used as collateral for flexible loans. Shows LTV ratios and collateral limits.", - { - collateralCoin: z.string().optional() - .describe("Filter by specific collateral coin (e.g., 'BTC', 'ETH')"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanCollateralAssetsData({ - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + collateralCoin: z + .string() + .optional() + .describe("Filter by specific collateral coin (e.g., 'BTC', 'ETH')"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await ( + cryptoLoanClient as any + ).restAPI.getFlexibleLoanCollateralAssetsData({ + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Flexible Loan Collateral Assets:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Flexible Loan Collateral Assets:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get collateral assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get collateral assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/getFlexibleLoanAssets.ts b/src/tools/binance-crypto-loans/flexible-api/getFlexibleLoanAssets.ts index f9d0fcdc..8f162c75 100644 --- a/src/tools/binance-crypto-loans/flexible-api/getFlexibleLoanAssets.ts +++ b/src/tools/binance-crypto-loans/flexible-api/getFlexibleLoanAssets.ts @@ -5,42 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/getFlexibleLoanAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleAssets", + server.registerTool( + "BinanceCryptoLoansFlexibleAssets", + { + description: "Get list of assets available for flexible crypto loans. Shows borrowable assets with interest rates and limits.", - { - loanCoin: z.string().optional() - .describe("Filter by specific loan coin (e.g., 'USDT', 'BUSD')"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanAssetsData({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z + .string() + .optional() + .describe("Filter by specific loan coin (e.g., 'USDT', 'BUSD')"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanAssetsData({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Flexible Loan Assets:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Flexible Loan Assets:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get loan assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get loan assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/getOngoingOrders.ts b/src/tools/binance-crypto-loans/flexible-api/getOngoingOrders.ts index c359d376..7345fe48 100644 --- a/src/tools/binance-crypto-loans/flexible-api/getOngoingOrders.ts +++ b/src/tools/binance-crypto-loans/flexible-api/getOngoingOrders.ts @@ -5,51 +5,54 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/getOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleOngoing(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleOngoing", + server.registerTool( + "BinanceCryptoLoansFlexibleOngoing", + { + description: "Get all ongoing flexible loan orders. Shows current loans with principal, interest, collateral, and LTV information.", - { - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - current: z.number().int().min(1).optional() - .describe("Current page (default 1)"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanOngoingOrders({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + current: z.number().int().min(1).optional().describe("Current page (default 1)"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanOngoingOrders({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Ongoing Flexible Loans:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Ongoing Flexible Loans:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get ongoing orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get ongoing orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/getRepayHistory.ts b/src/tools/binance-crypto-loans/flexible-api/getRepayHistory.ts index 85d65eb0..bc04ee3d 100644 --- a/src/tools/binance-crypto-loans/flexible-api/getRepayHistory.ts +++ b/src/tools/binance-crypto-loans/flexible-api/getRepayHistory.ts @@ -5,57 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/getRepayHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleRepayHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleRepayHistory", + server.registerTool( + "BinanceCryptoLoansFlexibleRepayHistory", + { + description: "Get repayment history for flexible loans. Shows all past repayment transactions.", - { - loanCoin: z.string().optional() - .describe("Filter by loan coin"), - collateralCoin: z.string().optional() - .describe("Filter by collateral coin"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - current: z.number().int().min(1).optional() - .describe("Current page (default 1)"), - limit: z.number().int().min(1).max(100).optional() - .describe("Results per page (max 100)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanRepaymentHistory({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Filter by loan coin"), + collateralCoin: z.string().optional().describe("Filter by collateral coin"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().min(1).optional().describe("Current page (default 1)"), + limit: z.number().int().min(1).max(100).optional().describe("Results per page (max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanRepaymentHistory({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Flexible Loan Repay History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Flexible Loan Repay History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get repay history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get repay history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexible-api/index.ts b/src/tools/binance-crypto-loans/flexible-api/index.ts index d8689ec3..624a4bf2 100644 --- a/src/tools/binance-crypto-loans/flexible-api/index.ts +++ b/src/tools/binance-crypto-loans/flexible-api/index.ts @@ -5,23 +5,24 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceCryptoLoansFlexibleAssets } from "./getFlexibleLoanAssets.js"; -import { registerBinanceCryptoLoansFlexibleCollateral } from "./getFlexibleCollateralAssets.js"; -import { registerBinanceCryptoLoansFlexibleBorrow } from "./borrow.js"; -import { registerBinanceCryptoLoansFlexibleRepay } from "./repay.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCryptoLoansFlexibleAdjustLTV } from "./adjustLTV.js"; -import { registerBinanceCryptoLoansFlexibleOngoing } from "./getOngoingOrders.js"; +import { registerBinanceCryptoLoansFlexibleBorrow } from "./borrow.js"; import { registerBinanceCryptoLoansFlexibleBorrowHistory } from "./getBorrowHistory.js"; +import { registerBinanceCryptoLoansFlexibleCollateral } from "./getFlexibleCollateralAssets.js"; +import { registerBinanceCryptoLoansFlexibleAssets } from "./getFlexibleLoanAssets.js"; +import { registerBinanceCryptoLoansFlexibleOngoing } from "./getOngoingOrders.js"; import { registerBinanceCryptoLoansFlexibleRepayHistory } from "./getRepayHistory.js"; +import { registerBinanceCryptoLoansFlexibleRepay } from "./repay.js"; export function registerBinanceCryptoLoansFlexibleTools(server: McpServer) { - registerBinanceCryptoLoansFlexibleAssets(server); - registerBinanceCryptoLoansFlexibleCollateral(server); - registerBinanceCryptoLoansFlexibleBorrow(server); - registerBinanceCryptoLoansFlexibleRepay(server); - registerBinanceCryptoLoansFlexibleAdjustLTV(server); - registerBinanceCryptoLoansFlexibleOngoing(server); - registerBinanceCryptoLoansFlexibleBorrowHistory(server); - registerBinanceCryptoLoansFlexibleRepayHistory(server); + registerBinanceCryptoLoansFlexibleAssets(server); + registerBinanceCryptoLoansFlexibleCollateral(server); + registerBinanceCryptoLoansFlexibleBorrow(server); + registerBinanceCryptoLoansFlexibleRepay(server); + registerBinanceCryptoLoansFlexibleAdjustLTV(server); + registerBinanceCryptoLoansFlexibleOngoing(server); + registerBinanceCryptoLoansFlexibleBorrowHistory(server); + registerBinanceCryptoLoansFlexibleRepayHistory(server); } diff --git a/src/tools/binance-crypto-loans/flexible-api/repay.ts b/src/tools/binance-crypto-loans/flexible-api/repay.ts index 138070e7..b152f98b 100644 --- a/src/tools/binance-crypto-loans/flexible-api/repay.ts +++ b/src/tools/binance-crypto-loans/flexible-api/repay.ts @@ -5,54 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-crypto-loans/flexible-api/repay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCryptoLoansFlexibleRepay(server: McpServer) { - server.tool( - "BinanceCryptoLoansFlexibleRepay", + server.registerTool( + "BinanceCryptoLoansFlexibleRepay", + { + description: "Repay a flexible crypto loan. Repaying reduces your debt and unlocks collateral proportionally.", - { - loanCoin: z.string() - .describe("Loan coin to repay (e.g., 'USDT')"), - collateralCoin: z.string() - .describe("Collateral coin used for the loan (e.g., 'BTC')"), - repayAmount: z.string() - .describe("Amount to repay"), - collateralReturn: z.boolean().optional() - .describe("Whether to return collateral after full repayment (default: true)"), - fullRepayment: z.boolean().optional() - .describe("Whether this is a full repayment"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.flexibleLoanRepay({ - loanCoin: params.loanCoin, - collateralCoin: params.collateralCoin, - repayAmount: params.repayAmount, - ...(params.collateralReturn !== undefined && { collateralReturn: params.collateralReturn }), - ...(params.fullRepayment !== undefined && { fullRepayment: params.fullRepayment }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().describe("Loan coin to repay (e.g., 'USDT')"), + collateralCoin: z.string().describe("Collateral coin used for the loan (e.g., 'BTC')"), + repayAmount: z.string().describe("Amount to repay"), + collateralReturn: z + .boolean() + .optional() + .describe("Whether to return collateral after full repayment (default: true)"), + fullRepayment: z.boolean().optional().describe("Whether this is a full repayment"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanRepay({ + loanCoin: params.loanCoin, + collateralCoin: params.collateralCoin, + repayAmount: params.repayAmount, + ...(params.collateralReturn !== undefined && { + collateralReturn: params.collateralReturn, + }), + ...(params.fullRepayment !== undefined && { fullRepayment: params.fullRepayment }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Loan Repayment Successful!\n\nRepaid: ${params.repayAmount} ${params.loanCoin}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Loan Repayment Successful!\n\nRepaid: ${params.repayAmount} ${params.loanCoin}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to repay loan: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to repay loan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanAdjustLTV.ts b/src/tools/binance-crypto-loans/flexibleLoanAdjustLTV.ts index 0539fe8c..ceddfaf1 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanAdjustLTV.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanAdjustLTV.ts @@ -1,41 +1,47 @@ // src/tools/binance-crypto-loans/flexibleLoanAdjustLTV.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanAdjustLTV(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanAdjustLTV", - "Flexible loan adjust LTV (Loan-to-Value).", - { - loanCoin: z.string().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), - adjustmentAmount: z.number().describe("Adjustment amount"), - direction: z.enum(["ADDITIONAL", "REDUCED"]).describe("Direction: ADDITIONAL = add collateral, REDUCED = reduce collateral") - }, - async ({ loanCoin, collateralCoin, adjustmentAmount, direction }) => { - try { - const params: any = { loanCoin, collateralCoin, adjustmentAmount, direction }; - - const response = await cryptoLoanClient.restAPI.flexibleLoanAdjustLtv(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan LTV adjusted successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to adjust flexible loan LTV: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanAdjustLTV", + { + description: "Flexible loan adjust LTV (Loan-to-Value).", + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), + adjustmentAmount: z.number().describe("Adjustment amount"), + direction: z + .enum(["ADDITIONAL", "REDUCED"]) + .describe("Direction: ADDITIONAL = add collateral, REDUCED = reduce collateral"), + }, + }, + async ({ loanCoin, collateralCoin, adjustmentAmount, direction }) => { + try { + const params: any = { loanCoin, collateralCoin, adjustmentAmount, direction }; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanAdjustLtv(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan LTV adjusted successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to adjust flexible loan LTV: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanBorrow.ts b/src/tools/binance-crypto-loans/flexibleLoanBorrow.ts index b7c7c20d..32d06543 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanBorrow.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanBorrow.ts @@ -1,43 +1,47 @@ // src/tools/binance-crypto-loans/flexibleLoanBorrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanBorrow(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanBorrow", - "Flexible loan borrow.", - { - loanCoin: z.string().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), - loanAmount: z.number().optional().describe("Loan amount"), - collateralAmount: z.number().optional().describe("Collateral amount") - }, - async ({ loanCoin, collateralCoin, loanAmount, collateralAmount }) => { - try { - const params: any = { loanCoin, collateralCoin }; - if (loanAmount !== undefined) params.loanAmount = loanAmount; - if (collateralAmount !== undefined) params.collateralAmount = collateralAmount; - - const response = await cryptoLoanClient.restAPI.flexibleLoanBorrow(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan borrowed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to borrow flexible loan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanBorrow", + { + description: "Flexible loan borrow.", + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), + loanAmount: z.number().optional().describe("Loan amount"), + collateralAmount: z.number().optional().describe("Collateral amount"), + }, + }, + async ({ loanCoin, collateralCoin, loanAmount, collateralAmount }) => { + try { + const params: any = { loanCoin, collateralCoin }; + if (loanAmount !== undefined) params.loanAmount = loanAmount; + if (collateralAmount !== undefined) params.collateralAmount = collateralAmount; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanBorrow(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan borrowed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to borrow flexible loan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanBorrowHistory.ts b/src/tools/binance-crypto-loans/flexibleLoanBorrowHistory.ts index 88aff89f..ac7d04b3 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanBorrowHistory.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanBorrowHistory.ts @@ -1,49 +1,55 @@ // src/tools/binance-crypto-loans/flexibleLoanBorrowHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanBorrowHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanBorrowHistory", - "Get flexible loan borrow history.", - { - loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - limit: z.number().optional().describe("Page size, max 100") - }, - async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { - try { - const params: any = {}; - if (loanCoin) params.loanCoin = loanCoin; - if (collateralCoin) params.collateralCoin = collateralCoin; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (limit !== undefined) params.limit = limit; - - const response = await cryptoLoanClient.restAPI.flexibleLoanBorrowHistory(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan borrow history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get flexible loan borrow history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanBorrowHistory", + { + description: "Get flexible loan borrow history.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + limit: z.number().optional().describe("Page size, max 100"), + }, + }, + async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { + try { + const params: any = {}; + if (loanCoin) params.loanCoin = loanCoin; + if (collateralCoin) params.collateralCoin = collateralCoin; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (limit !== undefined) params.limit = limit; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanBorrowHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan borrow history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get flexible loan borrow history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanCollateralAssets.ts b/src/tools/binance-crypto-loans/flexibleLoanCollateralAssets.ts index 5bcf949f..273c4c5f 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanCollateralAssets.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanCollateralAssets.ts @@ -1,39 +1,50 @@ // src/tools/binance-crypto-loans/flexibleLoanCollateralAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanCollateralAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanCollateralAssets", - "Get flexible loan collateral assets.", - { - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)") - }, - async ({ collateralCoin }) => { - try { - const params: any = {}; - if (collateralCoin) params.collateralCoin = collateralCoin; - - const response = await cryptoLoanClient.restAPI.getFlexibleLoanCollateralAssetsData(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan collateral assets retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get flexible loan collateral assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanCollateralAssets", + { + description: "Get flexible loan collateral assets.", + inputSchema: { + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + }, + }, + async ({ collateralCoin }) => { + try { + const params: any = {}; + if (collateralCoin) params.collateralCoin = collateralCoin; + + const response = await ( + cryptoLoanClient as any + ).restAPI.getFlexibleLoanCollateralAssetsData(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan collateral assets retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to get flexible loan collateral assets: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanLTVAdjustmentHistory.ts b/src/tools/binance-crypto-loans/flexibleLoanLTVAdjustmentHistory.ts index 822c7020..76319d6a 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanLTVAdjustmentHistory.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanLTVAdjustmentHistory.ts @@ -1,49 +1,60 @@ // src/tools/binance-crypto-loans/flexibleLoanLTVAdjustmentHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory", - "Get flexible loan LTV adjustment history.", - { - loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - limit: z.number().optional().describe("Page size, max 100") - }, - async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { - try { - const params: any = {}; - if (loanCoin) params.loanCoin = loanCoin; - if (collateralCoin) params.collateralCoin = collateralCoin; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (limit !== undefined) params.limit = limit; - - const response = await cryptoLoanClient.restAPI.getFlexibleLoanLtvAdjustmentHistory(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan LTV adjustment history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get flexible loan LTV adjustment history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory", + { + description: "Get flexible loan LTV adjustment history.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + limit: z.number().optional().describe("Page size, max 100"), + }, + }, + async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { + try { + const params: any = {}; + if (loanCoin) params.loanCoin = loanCoin; + if (collateralCoin) params.collateralCoin = collateralCoin; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (limit !== undefined) params.limit = limit; + + const response = await ( + cryptoLoanClient as any + ).restAPI.getFlexibleLoanLtvAdjustmentHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan LTV adjustment history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to get flexible loan LTV adjustment history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanLoanableAssets.ts b/src/tools/binance-crypto-loans/flexibleLoanLoanableAssets.ts index d7fb8897..77694287 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanLoanableAssets.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanLoanableAssets.ts @@ -1,33 +1,43 @@ // src/tools/binance-crypto-loans/flexibleLoanLoanableAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { cryptoLoanClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { cryptoLoanClient } from "../../config/binanceClient.js"; + export function registerBinanceCryptoLoanFlexibleLoanableAssets(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanableAssets", - "Get flexible loan loanable assets data.", - { - loanCoin: z.string().optional().describe("Loan coin"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await cryptoLoanClient.restAPI.getFlexibleLoanAssets({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ type: "text", text: `Flexible loan loanable assets: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get flexible loan loanable assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanableAssets", + { + description: "Get flexible loan loanable assets data.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanAssets({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { type: "text", text: `Flexible loan loanable assets: ${JSON.stringify(data)}` }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get flexible loan loanable assets: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanOngoingOrders.ts b/src/tools/binance-crypto-loans/flexibleLoanOngoingOrders.ts index 87b3dab8..12e471f8 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanOngoingOrders.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanOngoingOrders.ts @@ -1,45 +1,51 @@ // src/tools/binance-crypto-loans/flexibleLoanOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanOngoingOrders(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanOngoingOrders", - "Get flexible loan ongoing orders.", - { - loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), - current: z.number().optional().describe("Current page"), - limit: z.number().optional().describe("Page size, max 100") - }, - async ({ loanCoin, collateralCoin, current, limit }) => { - try { - const params: any = {}; - if (loanCoin) params.loanCoin = loanCoin; - if (collateralCoin) params.collateralCoin = collateralCoin; - if (current !== undefined) params.current = current; - if (limit !== undefined) params.limit = limit; - - const response = await cryptoLoanClient.restAPI.flexibleLoanOngoingOrders(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan ongoing orders retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get flexible loan ongoing orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanOngoingOrders", + { + description: "Get flexible loan ongoing orders.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + current: z.number().optional().describe("Current page"), + limit: z.number().optional().describe("Page size, max 100"), + }, + }, + async ({ loanCoin, collateralCoin, current, limit }) => { + try { + const params: any = {}; + if (loanCoin) params.loanCoin = loanCoin; + if (collateralCoin) params.collateralCoin = collateralCoin; + if (current !== undefined) params.current = current; + if (limit !== undefined) params.limit = limit; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanOngoingOrders(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan ongoing orders retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get flexible loan ongoing orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanRepay.ts b/src/tools/binance-crypto-loans/flexibleLoanRepay.ts index 2c69ffa1..5554e9f5 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanRepay.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanRepay.ts @@ -1,44 +1,48 @@ // src/tools/binance-crypto-loans/flexibleLoanRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanRepay(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanRepay", - "Flexible loan repay.", - { - loanCoin: z.string().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), - repayAmount: z.number().describe("Repay amount"), - collateralReturn: z.boolean().optional().describe("Whether to return collateral"), - fullRepayment: z.boolean().optional().describe("Whether to do full repayment") - }, - async ({ loanCoin, collateralCoin, repayAmount, collateralReturn, fullRepayment }) => { - try { - const params: any = { loanCoin, collateralCoin, repayAmount }; - if (collateralReturn !== undefined) params.collateralReturn = collateralReturn; - if (fullRepayment !== undefined) params.fullRepayment = fullRepayment; - - const response = await cryptoLoanClient.restAPI.flexibleLoanRepay(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan repaid successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to repay flexible loan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanRepay", + { + description: "Flexible loan repay.", + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), + repayAmount: z.number().describe("Repay amount"), + collateralReturn: z.boolean().optional().describe("Whether to return collateral"), + fullRepayment: z.boolean().optional().describe("Whether to do full repayment"), + }, + }, + async ({ loanCoin, collateralCoin, repayAmount, collateralReturn, fullRepayment }) => { + try { + const params: any = { loanCoin, collateralCoin, repayAmount }; + if (collateralReturn !== undefined) params.collateralReturn = collateralReturn; + if (fullRepayment !== undefined) params.fullRepayment = fullRepayment; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanRepay(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan repaid successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to repay flexible loan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/flexibleLoanRepayHistory.ts b/src/tools/binance-crypto-loans/flexibleLoanRepayHistory.ts index 8f81bc33..ad7f48c2 100644 --- a/src/tools/binance-crypto-loans/flexibleLoanRepayHistory.ts +++ b/src/tools/binance-crypto-loans/flexibleLoanRepayHistory.ts @@ -1,49 +1,57 @@ // src/tools/binance-crypto-loans/flexibleLoanRepayHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanFlexibleLoanRepayHistory(server: McpServer) { - server.tool( - "BinanceCryptoLoanFlexibleLoanRepayHistory", - "Get flexible loan repayment history.", - { - loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - limit: z.number().optional().describe("Page size, max 100") - }, - async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { - try { - const params: any = {}; - if (loanCoin) params.loanCoin = loanCoin; - if (collateralCoin) params.collateralCoin = collateralCoin; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (limit !== undefined) params.limit = limit; - - const response = await cryptoLoanClient.restAPI.flexibleLoanRepaymentHistory(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Flexible loan repay history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get flexible loan repay history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanFlexibleLoanRepayHistory", + { + description: "Get flexible loan repayment history.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + limit: z.number().optional().describe("Page size, max 100"), + }, + }, + async ({ loanCoin, collateralCoin, startTime, endTime, current, limit }) => { + try { + const params: any = {}; + if (loanCoin) params.loanCoin = loanCoin; + if (collateralCoin) params.collateralCoin = collateralCoin; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (limit !== undefined) params.limit = limit; + + const response = await (cryptoLoanClient as any).restAPI.flexibleLoanRepaymentHistory( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Flexible loan repay history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get flexible loan repay history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/getCollateralAssetsData.ts b/src/tools/binance-crypto-loans/getCollateralAssetsData.ts index 186ffa3f..d0d9d7e7 100644 --- a/src/tools/binance-crypto-loans/getCollateralAssetsData.ts +++ b/src/tools/binance-crypto-loans/getCollateralAssetsData.ts @@ -1,41 +1,49 @@ // src/tools/binance-crypto-loans/getCollateralAssetsData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanGetCollateralAssetsDataV2(server: McpServer) { - server.tool( - "BinanceCryptoLoanGetCollateralAssetsDataV2", - "Get collateral assets data V2 for flexible crypto loans.", - { - collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), - vipLevel: z.number().optional().describe("VIP level") - }, - async ({ collateralCoin, vipLevel }) => { - try { - const params: any = {}; - if (collateralCoin) params.collateralCoin = collateralCoin; - if (vipLevel !== undefined) params.vipLevel = vipLevel; - - const response = await cryptoLoanClient.restAPI.getFlexibleLoanCollateralAssetsData(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Collateral assets data V2 retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get collateral assets data V2: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanGetCollateralAssetsDataV2", + { + description: "Get collateral assets data V2 for flexible crypto loans.", + inputSchema: { + collateralCoin: z.string().optional().describe("Collateral coin (e.g., BTC)"), + vipLevel: z.number().optional().describe("VIP level"), + }, + }, + async ({ collateralCoin, vipLevel }) => { + try { + const params: any = {}; + if (collateralCoin) params.collateralCoin = collateralCoin; + if (vipLevel !== undefined) params.vipLevel = vipLevel; + + const response = await ( + cryptoLoanClient as any + ).restAPI.getFlexibleLoanCollateralAssetsData(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Collateral assets data V2 retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get collateral assets data V2: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/getCollateralRepayRate.ts b/src/tools/binance-crypto-loans/getCollateralRepayRate.ts index 7bf37688..5579376c 100644 --- a/src/tools/binance-crypto-loans/getCollateralRepayRate.ts +++ b/src/tools/binance-crypto-loans/getCollateralRepayRate.ts @@ -1,40 +1,44 @@ // src/tools/binance-crypto-loans/getCollateralRepayRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanGetCollateralRepayRate(server: McpServer) { - server.tool( - "BinanceCryptoLoanGetCollateralRepayRate", - "Check collateral repay rate for crypto loans.", - { - loanCoin: z.string().describe("Loan coin (e.g., USDT)"), - collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), - repayAmount: z.number().describe("Repay amount") - }, - async ({ loanCoin, collateralCoin, repayAmount }) => { - try { - const params: any = { loanCoin, collateralCoin, repayAmount }; - - const response = await cryptoLoanClient.restAPI.checkCollateralRepayRate(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Collateral repay rate retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get collateral repay rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanGetCollateralRepayRate", + { + description: "Check collateral repay rate for crypto loans.", + inputSchema: { + loanCoin: z.string().describe("Loan coin (e.g., USDT)"), + collateralCoin: z.string().describe("Collateral coin (e.g., BTC)"), + repayAmount: z.number().describe("Repay amount"), + }, + }, + async ({ loanCoin, collateralCoin, repayAmount }) => { + try { + const params: any = { loanCoin, collateralCoin, repayAmount }; + + const response = await (cryptoLoanClient as any).restAPI.checkCollateralRepayRate(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Collateral repay rate retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get collateral repay rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/getLoanableAssetsData.ts b/src/tools/binance-crypto-loans/getLoanableAssetsData.ts index 3201bb41..261d8872 100644 --- a/src/tools/binance-crypto-loans/getLoanableAssetsData.ts +++ b/src/tools/binance-crypto-loans/getLoanableAssetsData.ts @@ -1,41 +1,47 @@ // src/tools/binance-crypto-loans/getLoanableAssetsData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { cryptoLoanClient } from "../../config/binanceClient.js"; export function registerBinanceCryptoLoanGetLoanableAssetsDataV2(server: McpServer) { - server.tool( - "BinanceCryptoLoanGetLoanableAssetsDataV2", - "Get loanable assets data V2 for flexible crypto loans.", - { - loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), - vipLevel: z.number().optional().describe("VIP level") - }, - async ({ loanCoin, vipLevel }) => { - try { - const params: any = {}; - if (loanCoin) params.loanCoin = loanCoin; - if (vipLevel !== undefined) params.vipLevel = vipLevel; - - const response = await cryptoLoanClient.restAPI.getFlexibleLoanAssetsData(params); - const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Loanable assets data V2 retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get loanable assets data V2: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceCryptoLoanGetLoanableAssetsDataV2", + { + description: "Get loanable assets data V2 for flexible crypto loans.", + inputSchema: { + loanCoin: z.string().optional().describe("Loan coin (e.g., USDT)"), + vipLevel: z.number().optional().describe("VIP level"), + }, + }, + async ({ loanCoin, vipLevel }) => { + try { + const params: any = {}; + if (loanCoin) params.loanCoin = loanCoin; + if (vipLevel !== undefined) params.vipLevel = vipLevel; + + const response = await (cryptoLoanClient as any).restAPI.getFlexibleLoanAssetsData(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Loanable assets data V2 retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get loanable assets data V2: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-crypto-loans/index.ts b/src/tools/binance-crypto-loans/index.ts index d9fffb47..b7ebbc02 100644 --- a/src/tools/binance-crypto-loans/index.ts +++ b/src/tools/binance-crypto-loans/index.ts @@ -1,40 +1,38 @@ // src/tools/binance-crypto-loans/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; - -// Crypto Loans - Info -import { registerBinanceCryptoLoanGetCollateralRepayRate } from "./getCollateralRepayRate.js"; -import { registerBinanceCryptoLoanGetLoanableAssetsDataV2 } from "./getLoanableAssetsData.js"; -import { registerBinanceCryptoLoanGetCollateralAssetsDataV2 } from "./getCollateralAssetsData.js"; -import { registerBinanceCryptoLoanFlexibleLoanCollateralAssets } from "./flexibleLoanCollateralAssets.js"; -import { registerBinanceCryptoLoanFlexibleLoanableAssets } from "./flexibleLoanLoanableAssets.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { registerBinanceCryptoLoanFlexibleLoanAdjustLTV } from "./flexibleLoanAdjustLTV.js"; // Crypto Loans - Trading import { registerBinanceCryptoLoanFlexibleLoanBorrow } from "./flexibleLoanBorrow.js"; -import { registerBinanceCryptoLoanFlexibleLoanRepay } from "./flexibleLoanRepay.js"; -import { registerBinanceCryptoLoanFlexibleLoanAdjustLTV } from "./flexibleLoanAdjustLTV.js"; - +import { registerBinanceCryptoLoanFlexibleLoanBorrowHistory } from "./flexibleLoanBorrowHistory.js"; +import { registerBinanceCryptoLoanFlexibleLoanCollateralAssets } from "./flexibleLoanCollateralAssets.js"; +import { registerBinanceCryptoLoanFlexibleLoanableAssets } from "./flexibleLoanLoanableAssets.js"; +import { registerBinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory } from "./flexibleLoanLTVAdjustmentHistory.js"; // Crypto Loans - History import { registerBinanceCryptoLoanFlexibleLoanOngoingOrders } from "./flexibleLoanOngoingOrders.js"; -import { registerBinanceCryptoLoanFlexibleLoanBorrowHistory } from "./flexibleLoanBorrowHistory.js"; +import { registerBinanceCryptoLoanFlexibleLoanRepay } from "./flexibleLoanRepay.js"; import { registerBinanceCryptoLoanFlexibleLoanRepayHistory } from "./flexibleLoanRepayHistory.js"; -import { registerBinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory } from "./flexibleLoanLTVAdjustmentHistory.js"; +import { registerBinanceCryptoLoanGetCollateralAssetsDataV2 } from "./getCollateralAssetsData.js"; +// Crypto Loans - Info +import { registerBinanceCryptoLoanGetCollateralRepayRate } from "./getCollateralRepayRate.js"; +import { registerBinanceCryptoLoanGetLoanableAssetsDataV2 } from "./getLoanableAssetsData.js"; export function registerBinanceCryptoLoansTools(server: McpServer) { - // Crypto Loans - Info - registerBinanceCryptoLoanGetCollateralRepayRate(server); - registerBinanceCryptoLoanGetLoanableAssetsDataV2(server); - registerBinanceCryptoLoanGetCollateralAssetsDataV2(server); - registerBinanceCryptoLoanFlexibleLoanCollateralAssets(server); - registerBinanceCryptoLoanFlexibleLoanableAssets(server); - - // Crypto Loans - Trading - registerBinanceCryptoLoanFlexibleLoanBorrow(server); - registerBinanceCryptoLoanFlexibleLoanRepay(server); - registerBinanceCryptoLoanFlexibleLoanAdjustLTV(server); - - // Crypto Loans - History - registerBinanceCryptoLoanFlexibleLoanOngoingOrders(server); - registerBinanceCryptoLoanFlexibleLoanBorrowHistory(server); - registerBinanceCryptoLoanFlexibleLoanRepayHistory(server); - registerBinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory(server); + // Crypto Loans - Info + registerBinanceCryptoLoanGetCollateralRepayRate(server); + registerBinanceCryptoLoanGetLoanableAssetsDataV2(server); + registerBinanceCryptoLoanGetCollateralAssetsDataV2(server); + registerBinanceCryptoLoanFlexibleLoanCollateralAssets(server); + registerBinanceCryptoLoanFlexibleLoanableAssets(server); + + // Crypto Loans - Trading + registerBinanceCryptoLoanFlexibleLoanBorrow(server); + registerBinanceCryptoLoanFlexibleLoanRepay(server); + registerBinanceCryptoLoanFlexibleLoanAdjustLTV(server); + + // Crypto Loans - History + registerBinanceCryptoLoanFlexibleLoanOngoingOrders(server); + registerBinanceCryptoLoanFlexibleLoanBorrowHistory(server); + registerBinanceCryptoLoanFlexibleLoanRepayHistory(server); + registerBinanceCryptoLoanFlexibleLoanLTVAdjustmentHistory(server); } diff --git a/src/tools/binance-dual-investment/index.ts b/src/tools/binance-dual-investment/index.ts index 47e151ea..7a94024e 100644 --- a/src/tools/binance-dual-investment/index.ts +++ b/src/tools/binance-dual-investment/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-dual-investment/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDualInvestmentTradeApiTools } from "./trade-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDualInvestmentMarketApiTools } from "./market-api/index.js"; +import { registerBinanceDualInvestmentTradeApiTools } from "./trade-api/index.js"; export function registerBinanceDualInvestmentTools(server: McpServer) { - registerBinanceDualInvestmentTradeApiTools(server); - registerBinanceDualInvestmentMarketApiTools(server); + registerBinanceDualInvestmentTradeApiTools(server); + registerBinanceDualInvestmentMarketApiTools(server); } diff --git a/src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts b/src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts index 048f342d..3676a381 100644 --- a/src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts +++ b/src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts @@ -1,66 +1,72 @@ // src/tools/binance-dual-investment/market-api/getDualInvestmentProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetDualInvestmentProductList(server: McpServer) { - server.tool( - "BinanceGetDualInvestmentProductList", + server.registerTool( + "BinanceGetDualInvestmentProductList", + { + description: "Retrieve available Dual Investment products (CALL or PUT options), specifying invest and exercised coins, to view details like APR, strike price, duration, and purchase availability.", - { - optionType: z.enum(["CALL", "PUT"]).describe("Input CALL or PUT"), - exercisedCoin: z.string().describe("Target exercised asset, e.g., USDT or BNB"), - investCoin: z.string().describe("Asset used for subscribing, e.g., BNB or USDT"), - pageSize: z - .number() - .int() - .max(100, "Maximum pageSize is 100") - .default(10) - .optional() - .describe("Number of records per page, default 10, max 100"), - pageIndex: z.number().int().default(1).optional().describe("Page index, default is 1"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.getDualInvestmentProductList({ - optionType: params.optionType, - exercisedCoin: params.exercisedCoin, - investCoin: params.investCoin, - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + optionType: z.enum(["CALL", "PUT"]).describe("Input CALL or PUT"), + exercisedCoin: z.string().describe("Target exercised asset, e.g., USDT or BNB"), + investCoin: z.string().describe("Asset used for subscribing, e.g., BNB or USDT"), + pageSize: z + .number() + .int() + .max(100, "Maximum pageSize is 100") + .default(10) + .optional() + .describe("Number of records per page, default 10, max 100"), + pageIndex: z.number().int().default(1).optional().describe("Page index, default is 1"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.getDualInvestmentProductList({ + optionType: params.optionType, + exercisedCoin: params.exercisedCoin, + investCoin: params.investCoin, + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved available Dual Investment products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved available Dual Investment products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve available Dual Investment products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve available Dual Investment products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-dual-investment/market-api/index.ts b/src/tools/binance-dual-investment/market-api/index.ts index 5b6b81f2..f5465f8a 100644 --- a/src/tools/binance-dual-investment/market-api/index.ts +++ b/src/tools/binance-dual-investment/market-api/index.ts @@ -1,7 +1,8 @@ // src/tools/binance-dual-investment/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetDualInvestmentProductList } from "./getDualInvestmentProductList.js"; export function registerBinanceDualInvestmentMarketApiTools(server: McpServer) { - registerBinanceGetDualInvestmentProductList(server); + registerBinanceGetDualInvestmentProductList(server); } diff --git a/src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts b/src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts index 8904f7b9..888ad64b 100644 --- a/src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts +++ b/src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts @@ -1,57 +1,63 @@ // src/tools/binance-dual-investment/trade-api/changeAutoCompoundStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceChangeAutoCompoundStatus(server: McpServer) { - server.tool( - "registerBinanceChangeAutoCompoundStatus", + server.registerTool( + "registerBinanceChangeAutoCompoundStatus", + { + description: "Change the Auto-Compound plan for a Dual Investment position to NONE, STANDARD, or ADVANCED using the position ID.", - { - positionId: z.string().describe("Get positionId from /sapi/v1/dci/product/positions"), - autoCompoundPlan: z - .enum(["NONE", "STANDARD", "ADVANCED"]) - .optional() - .describe("Auto compound plan: NONE, STANDARD, or ADVANCED"), - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.changeAutoCompoundStatus({ - positionId: params.positionId, - autoCompoundPlan: params.autoCompoundPlan, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + positionId: z.string().describe("Get positionId from /sapi/v1/dci/product/positions"), + autoCompoundPlan: z + .enum(["NONE", "STANDARD", "ADVANCED"]) + .optional() + .describe("Auto compound plan: NONE, STANDARD, or ADVANCED"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.changeAutoCompoundStatus({ + positionId: params.positionId, + autoCompoundPlan: params.autoCompoundPlan, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Changed the Auto-Compound plan for a Dual Investment position. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Changed the Auto-Compound plan for a Dual Investment position. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to change the Auto-Compound plan for a Dual Investment position: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to change the Auto-Compound plan for a Dual Investment position: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts b/src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts index 0026a009..cca74369 100644 --- a/src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts +++ b/src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts @@ -1,50 +1,56 @@ // src/tools/binance-dual-investment/trade-api/checkDualInvestmentAccounts.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceCheckDualInvestmentAccounts(server: McpServer) { - server.tool( - "BinanceCheckDualInvestmentAccounts", + server.registerTool( + "BinanceCheckDualInvestmentAccounts", + { + description: "Retrieve Dual Investment account balances, including total value in BTC and USDT equivalents.", - { - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.checkDualInvestmentAccounts({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.checkDualInvestmentAccounts({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve Dual Investment account balances, including total value in BTC and USDT equivalents. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve Dual Investment account balances, including total value in BTC and USDT equivalents. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve Dual Investment account balances: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve Dual Investment account balances: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts b/src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts index 824c169e..34115870 100644 --- a/src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts +++ b/src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts @@ -1,75 +1,81 @@ // src/tools/binance-dual-investment/trade-api/getDualInvestmentPositions.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetDualInvestmentPositions(server: McpServer) { - server.tool( - "BinanceGetDualInvestmentPositions", + server.registerTool( + "BinanceGetDualInvestmentPositions", + { + description: "Fetch Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Filter by status or paginate results.", - { - status: z - .enum([ - "PENDING", - "PURCHASE_SUCCESS", - "SETTLED", - "PURCHASE_FAIL", - "REFUNDING", - "REFUND_SUCCESS", - "SETTLING" - ]) - .optional() - .describe( - "Position status: PENDING (awaiting results), PURCHASE_SUCCESS, SETTLED, PURCHASE_FAIL, REFUNDING, REFUND_SUCCESS, or SETTLING. If not provided, returns all." - ), - pageSize: z - .number() - .int() - .min(1) - .max(100) - .optional() - .describe("Number of items per page, default 10, max 100"), - pageIndex: z.number().int().min(1).optional().describe("Page index, default 1"), - recvWindow: z - .number() - .int() - .max(60000) - .optional() - .describe("Optional time window for request validity (max 60000)") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.getDualInvestmentPositions({ - ...(params.status && { status: params.status }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + status: z + .enum([ + "PENDING", + "PURCHASE_SUCCESS", + "SETTLED", + "PURCHASE_FAIL", + "REFUNDING", + "REFUND_SUCCESS", + "SETTLING", + ]) + .optional() + .describe( + "Position status: PENDING (awaiting results), PURCHASE_SUCCESS, SETTLED, PURCHASE_FAIL, REFUNDING, REFUND_SUCCESS, or SETTLING. If not provided, returns all.", + ), + pageSize: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Number of items per page, default 10, max 100"), + pageIndex: z.number().int().min(1).optional().describe("Page index, default 1"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Optional time window for request validity (max 60000)"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.getDualInvestmentPositions({ + ...(params.status && { status: params.status }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Fetched Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Fetched Dual Investment positions in batch, including status, subscription details, APR, and settlement info. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetch dual investment positions: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetch dual investment positions: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-dual-investment/trade-api/index.ts b/src/tools/binance-dual-investment/trade-api/index.ts index 5e0692bf..97d55f6c 100644 --- a/src/tools/binance-dual-investment/trade-api/index.ts +++ b/src/tools/binance-dual-investment/trade-api/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-dual-investment/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubscribeDualInvestmentProducts } from "./subscribeDualInvestmentProducts.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceChangeAutoCompoundStatus } from "./changeAutoCompoundStatus.js"; import { registerBinanceCheckDualInvestmentAccounts } from "./checkDualInvestmentAccounts.js"; import { registerBinanceGetDualInvestmentPositions } from "./getDualInvestmentPositions.js"; -import { registerBinanceChangeAutoCompoundStatus } from "./changeAutoCompoundStatus.js"; +import { registerBinanceSubscribeDualInvestmentProducts } from "./subscribeDualInvestmentProducts.js"; export function registerBinanceDualInvestmentTradeApiTools(server: McpServer) { - registerBinanceSubscribeDualInvestmentProducts(server); - registerBinanceCheckDualInvestmentAccounts(server); - registerBinanceGetDualInvestmentPositions(server); - registerBinanceChangeAutoCompoundStatus(server); + registerBinanceSubscribeDualInvestmentProducts(server); + registerBinanceCheckDualInvestmentAccounts(server); + registerBinanceGetDualInvestmentPositions(server); + registerBinanceChangeAutoCompoundStatus(server); } diff --git a/src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts b/src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts index 36fa6626..5f84f4d4 100644 --- a/src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts +++ b/src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts @@ -1,60 +1,66 @@ // src/tools/binance-dual-investment/trade-api/subscribeDualInvestmentProducts.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { dualInvestmentClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { dualInvestmentClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeDualInvestmentProducts(server: McpServer) { - server.tool( - "BinanceSubscribeDualInvestmentProducts", + server.registerTool( + "BinanceSubscribeDualInvestmentProducts", + { + description: "Subscribe to Dual Investment products by providing product ID, order ID, deposit amount, and auto compound plan to initiate investment with specified terms.", - { - id: z.string().describe("Product ID from /sapi/v1/dci/product/list"), - orderId: z.string().describe("Order ID from /sapi/v1/dci/product/list"), - depositAmount: z.number().positive().describe("The amount for subscribing"), - autoCompoundPlan: z - .enum(["NONE", "STANDARD", "ADVANCED"]) - .describe("Auto-compound plan: NONE (off), STANDARD, or ADVANCED"), - recvWindow: z - .number() - .int() - .max(60000, "recvWindow cannot be greater than 60000") - .optional() - .describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await dualInvestmentClient.restAPI.subscribeDualInvestmentProducts({ - id: params.id, - orderId: params.orderId, - depositAmount: params.depositAmount, - autoCompoundPlan: params.autoCompoundPlan, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + id: z.string().describe("Product ID from /sapi/v1/dci/product/list"), + orderId: z.string().describe("Order ID from /sapi/v1/dci/product/list"), + depositAmount: z.number().positive().describe("The amount for subscribing"), + autoCompoundPlan: z + .enum(["NONE", "STANDARD", "ADVANCED"]) + .describe("Auto-compound plan: NONE (off), STANDARD, or ADVANCED"), + recvWindow: z + .number() + .int() + .max(60000, "recvWindow cannot be greater than 60000") + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await dualInvestmentClient.restAPI.subscribeDualInvestmentProducts({ + id: params.id, + orderId: params.orderId, + depositAmount: params.depositAmount, + autoCompoundPlan: params.autoCompoundPlan, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully subscribed to Dual Investment products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully subscribed to Dual Investment products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to subscribe to dual investment products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to subscribe to dual investment products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts b/src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts index feff9fbb..9b7e5f96 100644 --- a/src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts +++ b/src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts @@ -1,60 +1,72 @@ // src/tools/binance-fiat/fiat-api/getFiatDepositWithdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { fiatClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { fiatClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFiatDepositWithdrawHistory(server: McpServer) { - server.tool( - "BinanceGetFiatDepositWithdrawHistory", + server.registerTool( + "BinanceGetFiatDepositWithdrawHistory", + { + description: "Fetches fiat deposit or withdrawal history, showing transaction details like amount, currency, method, status, and timestamps.", - { - transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for deposit, 1 for withdraw"), - beginTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - rows: z - .number() - .int() - .max(500, "Rows cannot be greater than 500") - .optional() - .describe("Number of records per page, default 100, max 500"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await fiatClient.restAPI.getFiatDepositWithdrawHistory({ - transactionType: params.transactionType, - ...(params.beginTime && { beginTime: params.beginTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.rows && { rows: params.rows }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + transactionType: z + .enum(["0", "1"]) + .describe("Transaction type: 0 for deposit, 1 for withdraw"), + beginTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + rows: z + .number() + .int() + .max(500, "Rows cannot be greater than 500") + .optional() + .describe("Number of records per page, default 100, max 500"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await fiatClient.restAPI.getFiatDepositWithdrawHistory({ + transactionType: params.transactionType, + ...(params.beginTime && { beginTime: params.beginTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.rows && { rows: params.rows }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched fiat deposit or withdrawal history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched fiat deposit or withdrawal history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetches fiat deposit or withdrawal history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetches fiat deposit or withdrawal history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts b/src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts index 330a61a3..b2e4a1dc 100644 --- a/src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts +++ b/src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts @@ -1,60 +1,70 @@ // src/tools/binance-fiat/fiat-api/getFiatPaymentsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { fiatClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { fiatClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFiatPaymentsHistory(server: McpServer) { - server.tool( - "BinanceGetFiatPaymentsHistory", + server.registerTool( + "BinanceGetFiatPaymentsHistory", + { + description: "Retrieves fiat buy/sell payment history, including trade amount, currency, crypto received, fees, status, payment method, and timestamps.", - { - transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for buy, 1 for sell"), - beginTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().optional().describe("Page number, default is 1"), - rows: z - .number() - .int() - .max(500, "Rows cannot be greater than 500") - .optional() - .describe("Number of records per page, default 100, max 500"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await fiatClient.restAPI.getFiatPaymentsHistory({ - transactionType: params.transactionType, - ...(params.beginTime && { beginTime: params.beginTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.rows && { rows: params.rows }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + transactionType: z.enum(["0", "1"]).describe("Transaction type: 0 for buy, 1 for sell"), + beginTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().optional().describe("Page number, default is 1"), + rows: z + .number() + .int() + .max(500, "Rows cannot be greater than 500") + .optional() + .describe("Number of records per page, default 100, max 500"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await fiatClient.restAPI.getFiatPaymentsHistory({ + transactionType: params.transactionType, + ...(params.beginTime && { beginTime: params.beginTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.rows && { rows: params.rows }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved fiat buy/sell payment history. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved fiat buy/sell payment history. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve fiat buy/sell payment history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve fiat buy/sell payment history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-fiat/index.ts b/src/tools/binance-fiat/index.ts index d5556812..fbd6ba57 100644 --- a/src/tools/binance-fiat/index.ts +++ b/src/tools/binance-fiat/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-fiat/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFiatDepositWithdrawHistory } from "./fiat-api/getFiatDepositWithdrawHistory.js"; import { registerBinanceGetFiatPaymentsHistory } from "./fiat-api/getFiatPaymentsHistory.js"; export function registerBinanceFiatDepositWithdrawHistoryTools(server: McpServer) { - registerBinanceGetFiatDepositWithdrawHistory(server); - registerBinanceGetFiatPaymentsHistory(server); + registerBinanceGetFiatDepositWithdrawHistory(server); + registerBinanceGetFiatPaymentsHistory(server); } diff --git a/src/tools/binance-futures-coinm/account-api/account.ts b/src/tools/binance-futures-coinm/account-api/account.ts index c52dfda5..fadf824e 100644 --- a/src/tools/binance-futures-coinm/account-api/account.ts +++ b/src/tools/binance-futures-coinm/account-api/account.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/account.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryAccount(server: McpServer) { - server.tool( - "BinanceDeliveryAccount", + server.registerTool( + "BinanceDeliveryAccount", + { + description: "Get current COIN-M Futures account information including assets, positions, and risk metrics.", - { - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.account({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 COIN-M Futures Account Information\n\nCan Trade: ${data.canTrade}\nCan Deposit: ${data.canDeposit}\nCan Withdraw: ${data.canWithdraw}\nUpdate Time: ${new Date(data.updateTime).toISOString()}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get account info: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.account({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 COIN-M Futures Account Information\n\nCan Trade: ${data.canTrade}\nCan Deposit: ${data.canDeposit}\nCan Withdraw: ${data.canWithdraw}\nUpdate Time: ${new Date(data.updateTime).toISOString()}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get account info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/adlQuantile.ts b/src/tools/binance-futures-coinm/account-api/adlQuantile.ts index 38d674f0..c97e0a2b 100644 --- a/src/tools/binance-futures-coinm/account-api/adlQuantile.ts +++ b/src/tools/binance-futures-coinm/account-api/adlQuantile.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/adlQuantile.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryAdlQuantile(server: McpServer) { - server.tool( - "BinanceDeliveryAdlQuantile", + server.registerTool( + "BinanceDeliveryAdlQuantile", + { + description: "Get ADL (Auto-Deleveraging) quantile estimation for COIN-M Futures positions. Higher values indicate higher priority for deleveraging.", - { - symbol: z.string().optional().describe("Contract symbol filter"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.adlQuantile({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `⚠️ COIN-M ADL Quantile${params.symbol ? ` for ${params.symbol}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get ADL quantile: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().optional().describe("Contract symbol filter"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.adlQuantile({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `⚠️ COIN-M ADL Quantile${params.symbol ? ` for ${params.symbol}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get ADL quantile: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/balance.ts b/src/tools/binance-futures-coinm/account-api/balance.ts index d1b213fa..3b739867 100644 --- a/src/tools/binance-futures-coinm/account-api/balance.ts +++ b/src/tools/binance-futures-coinm/account-api/balance.ts @@ -5,38 +5,45 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/balance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryBalance(server: McpServer) { - server.tool( - "BinanceDeliveryBalance", - "Get current COIN-M Futures account balance.", - { - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.balance({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `💰 COIN-M Futures Balance\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get balance: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryBalance", + { + description: "Get current COIN-M Futures account balance.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.balance({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `💰 COIN-M Futures Balance\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/commissionRate.ts b/src/tools/binance-futures-coinm/account-api/commissionRate.ts index 9c64531d..1bc92a49 100644 --- a/src/tools/binance-futures-coinm/account-api/commissionRate.ts +++ b/src/tools/binance-futures-coinm/account-api/commissionRate.ts @@ -5,40 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/commissionRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCommissionRate(server: McpServer) { - server.tool( - "BinanceDeliveryCommissionRate", - "Get user's COIN-M Futures commission rate for a symbol.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.commissionRate({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `💰 COIN-M Commission Rate for ${params.symbol}\n\nMaker: ${data.makerCommissionRate}\nTaker: ${data.takerCommissionRate}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get commission rate: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryCommissionRate", + { + description: "Get user's COIN-M Futures commission rate for a symbol.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.commissionRate({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `💰 COIN-M Commission Rate for ${params.symbol}\n\nMaker: ${data.makerCommissionRate}\nTaker: ${data.takerCommissionRate}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get commission rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/forceOrders.ts b/src/tools/binance-futures-coinm/account-api/forceOrders.ts index 56517c4a..a9368ebd 100644 --- a/src/tools/binance-futures-coinm/account-api/forceOrders.ts +++ b/src/tools/binance-futures-coinm/account-api/forceOrders.ts @@ -5,48 +5,55 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/forceOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryForceOrders(server: McpServer) { - server.tool( - "BinanceDeliveryForceOrders", - "Get user's COIN-M Futures force (liquidation) order history.", - { - symbol: z.string().optional().describe("Contract symbol filter"), - autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("LIQUIDATION or ADL"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 50, max 100)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.forceOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.autoCloseType && { autoCloseType: params.autoCloseType }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `⚠️ COIN-M Force Orders (Liquidations)\n\nOrders: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get force orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryForceOrders", + { + description: "Get user's COIN-M Futures force (liquidation) order history.", + inputSchema: { + symbol: z.string().optional().describe("Contract symbol filter"), + autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("LIQUIDATION or ADL"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 50, max 100)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.forceOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.autoCloseType && { autoCloseType: params.autoCloseType }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `⚠️ COIN-M Force Orders (Liquidations)\n\nOrders: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get force orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/income.ts b/src/tools/binance-futures-coinm/account-api/income.ts index 59e69fff..eeaae0a1 100644 --- a/src/tools/binance-futures-coinm/account-api/income.ts +++ b/src/tools/binance-futures-coinm/account-api/income.ts @@ -5,52 +5,71 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/income.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryIncome(server: McpServer) { - server.tool( - "BinanceDeliveryIncome", + server.registerTool( + "BinanceDeliveryIncome", + { + description: "Get COIN-M Futures income history including realized PnL, funding fees, commissions, etc.", - { - symbol: z.string().optional().describe("Contract symbol filter"), - incomeType: z.enum([ - "TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", - "COMMISSION", "INSURANCE_CLEAR", "REFERRAL_KICKBACK", - "COMMISSION_REBATE", "DELIVERED_SETTELMENT", "COIN_SWAP_DEPOSIT", "COIN_SWAP_WITHDRAW" - ]).optional().describe("Income type filter"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 100, max 1000)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.income({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.incomeType && { incomeType: params.incomeType }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `💵 COIN-M Income History\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get income history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().optional().describe("Contract symbol filter"), + incomeType: z + .enum([ + "TRANSFER", + "WELCOME_BONUS", + "REALIZED_PNL", + "FUNDING_FEE", + "COMMISSION", + "INSURANCE_CLEAR", + "REFERRAL_KICKBACK", + "COMMISSION_REBATE", + "DELIVERED_SETTELMENT", + "COIN_SWAP_DEPOSIT", + "COIN_SWAP_WITHDRAW", + ]) + .optional() + .describe("Income type filter"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 100, max 1000)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.income({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.incomeType && { incomeType: params.incomeType }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `💵 COIN-M Income History\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get income history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/index.ts b/src/tools/binance-futures-coinm/account-api/index.ts index 2a0af311..7faba764 100644 --- a/src/tools/binance-futures-coinm/account-api/index.ts +++ b/src/tools/binance-futures-coinm/account-api/index.ts @@ -5,34 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDeliveryAccount } from "./account.js"; +import { registerBinanceDeliveryAdlQuantile } from "./adlQuantile.js"; import { registerBinanceDeliveryBalance } from "./balance.js"; -import { registerBinanceDeliveryPositionRisk } from "./positionRisk.js"; -import { registerBinanceDeliveryUserTrades } from "./userTrades.js"; +import { registerBinanceDeliveryCommissionRate } from "./commissionRate.js"; +import { registerBinanceDeliveryForceOrders } from "./forceOrders.js"; import { registerBinanceDeliveryIncome } from "./income.js"; import { registerBinanceDeliveryLeverageBracket } from "./leverageBracket.js"; -import { registerBinanceDeliveryAdlQuantile } from "./adlQuantile.js"; -import { registerBinanceDeliveryForceOrders } from "./forceOrders.js"; -import { registerBinanceDeliveryCommissionRate } from "./commissionRate.js"; import { registerBinanceDeliveryPositionMode } from "./positionMode.js"; +import { registerBinanceDeliveryPositionRisk } from "./positionRisk.js"; +import { registerBinanceDeliveryUserTrades } from "./userTrades.js"; export function registerBinanceDeliveryAccountApiTools(server: McpServer) { - // Account Information - registerBinanceDeliveryAccount(server); - registerBinanceDeliveryBalance(server); - registerBinanceDeliveryPositionRisk(server); - - // Trade History - registerBinanceDeliveryUserTrades(server); - registerBinanceDeliveryIncome(server); - - // Leverage & Risk - registerBinanceDeliveryLeverageBracket(server); - registerBinanceDeliveryAdlQuantile(server); - registerBinanceDeliveryForceOrders(server); - - // Account Settings - registerBinanceDeliveryCommissionRate(server); - registerBinanceDeliveryPositionMode(server); + // Account Information + registerBinanceDeliveryAccount(server); + registerBinanceDeliveryBalance(server); + registerBinanceDeliveryPositionRisk(server); + + // Trade History + registerBinanceDeliveryUserTrades(server); + registerBinanceDeliveryIncome(server); + + // Leverage & Risk + registerBinanceDeliveryLeverageBracket(server); + registerBinanceDeliveryAdlQuantile(server); + registerBinanceDeliveryForceOrders(server); + + // Account Settings + registerBinanceDeliveryCommissionRate(server); + registerBinanceDeliveryPositionMode(server); } diff --git a/src/tools/binance-futures-coinm/account-api/leverageBracket.ts b/src/tools/binance-futures-coinm/account-api/leverageBracket.ts index c135c290..f36b5e48 100644 --- a/src/tools/binance-futures-coinm/account-api/leverageBracket.ts +++ b/src/tools/binance-futures-coinm/account-api/leverageBracket.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/leverageBracket.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryLeverageBracket(server: McpServer) { - server.tool( - "BinanceDeliveryLeverageBracket", + server.registerTool( + "BinanceDeliveryLeverageBracket", + { + description: "Get notional and leverage bracket information for COIN-M Futures. Shows max leverage at different position sizes.", - { - pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.leverageBracket({ - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 COIN-M Leverage Brackets${params.pair ? ` for ${params.pair}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get leverage brackets: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.leverageBracket({ + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 COIN-M Leverage Brackets${params.pair ? ` for ${params.pair}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get leverage brackets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/positionMode.ts b/src/tools/binance-futures-coinm/account-api/positionMode.ts index 4bb7521f..db6f6c34 100644 --- a/src/tools/binance-futures-coinm/account-api/positionMode.ts +++ b/src/tools/binance-futures-coinm/account-api/positionMode.ts @@ -5,39 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/positionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryPositionMode(server: McpServer) { - server.tool( - "BinanceDeliveryPositionMode", - "Get current COIN-M Futures position mode (Hedge Mode or One-way Mode).", - { - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.getPositionMode({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const mode = data.dualSidePosition ? "Hedge Mode (LONG/SHORT)" : "One-way Mode (BOTH)"; - - return { - content: [{ - type: "text", - text: `⚙️ COIN-M Position Mode\n\nCurrent Mode: ${mode}\ndualSidePosition: ${data.dualSidePosition}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get position mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryPositionMode", + { + description: "Get current COIN-M Futures position mode (Hedge Mode or One-way Mode).", + inputSchema: { + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.getPositionMode({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const mode = data.dualSidePosition ? "Hedge Mode (LONG/SHORT)" : "One-way Mode (BOTH)"; + + return { + content: [ + { + type: "text", + text: `⚙️ COIN-M Position Mode\n\nCurrent Mode: ${mode}\ndualSidePosition: ${data.dualSidePosition}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get position mode: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/positionRisk.ts b/src/tools/binance-futures-coinm/account-api/positionRisk.ts index 4ffd35f9..fe074f7e 100644 --- a/src/tools/binance-futures-coinm/account-api/positionRisk.ts +++ b/src/tools/binance-futures-coinm/account-api/positionRisk.ts @@ -5,42 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/positionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryPositionRisk(server: McpServer) { - server.tool( - "BinanceDeliveryPositionRisk", + server.registerTool( + "BinanceDeliveryPositionRisk", + { + description: "Get current COIN-M Futures position information including unrealized PnL and liquidation price.", - { - marginAsset: z.string().optional().describe("Filter by margin asset (e.g., BTC)"), - pair: z.string().optional().describe("Filter by trading pair (e.g., BTCUSD)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.positionRisk({ - ...(params.marginAsset && { marginAsset: params.marginAsset }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 COIN-M Position Risk\n\nPositions: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get position risk: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + marginAsset: z.string().optional().describe("Filter by margin asset (e.g., BTC)"), + pair: z.string().optional().describe("Filter by trading pair (e.g., BTCUSD)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.positionRisk({ + ...(params.marginAsset && { marginAsset: params.marginAsset }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 COIN-M Position Risk\n\nPositions: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get position risk: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account-api/userTrades.ts b/src/tools/binance-futures-coinm/account-api/userTrades.ts index 1202e24b..ed501673 100644 --- a/src/tools/binance-futures-coinm/account-api/userTrades.ts +++ b/src/tools/binance-futures-coinm/account-api/userTrades.ts @@ -5,50 +5,57 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/account-api/userTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryUserTrades(server: McpServer) { - server.tool( - "BinanceDeliveryUserTrades", - "Get COIN-M Futures account trade history for a symbol.", - { - symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP)"), - pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to fetch from"), - limit: z.number().int().optional().describe("Number of results (default 50, max 1000)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.userTrades({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📈 COIN-M Trade History\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get user trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryUserTrades", + { + description: "Get COIN-M Futures account trade history for a symbol.", + inputSchema: { + symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP)"), + pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to fetch from"), + limit: z.number().int().optional().describe("Number of results (default 50, max 1000)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.userTrades({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📈 COIN-M Trade History\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get user trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/account.ts b/src/tools/binance-futures-coinm/account.ts index 60a4b842..aad98f27 100644 --- a/src/tools/binance-futures-coinm/account.ts +++ b/src/tools/binance-futures-coinm/account.ts @@ -1,31 +1,36 @@ // src/tools/binance-futures-coinm/account.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMAccount(server: McpServer) { - server.tool( - "BinanceFuturesCOINMAccount", - "Get current COIN-M futures account information.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.getAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M account info: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get COIN-M account: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMAccount", + { + description: "Get current COIN-M futures account information.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.account({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M account info: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get COIN-M account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/adlQuantile.ts b/src/tools/binance-futures-coinm/adlQuantile.ts index 49ab4fb3..8d6cdabf 100644 --- a/src/tools/binance-futures-coinm/adlQuantile.ts +++ b/src/tools/binance-futures-coinm/adlQuantile.ts @@ -1,40 +1,52 @@ // src/tools/binance-futures-coinm/adlQuantile.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMADLQuantile(server: McpServer) { - server.tool( - "BinanceFuturesCOINMADLQuantile", - "Get position ADL (Auto-Deleveraging) quantile estimate for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all positions") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesCOINMADLQuantile", + { + description: "Get position ADL (Auto-Deleveraging) quantile estimate for COIN-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all positions", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await deliveryClient.adlQuantile(params); - const data = await deliveryClient.adlQuantile(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures ADL quantile${symbol ? ` for ${symbol}` : " for all positions"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures ADL quantile${symbol ? ` for ${symbol}` : ' for all positions'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures ADL quantile: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures ADL quantile: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/aggTrades.ts b/src/tools/binance-futures-coinm/aggTrades.ts index 47a14995..5861ff10 100644 --- a/src/tools/binance-futures-coinm/aggTrades.ts +++ b/src/tools/binance-futures-coinm/aggTrades.ts @@ -1,47 +1,60 @@ // src/tools/binance-futures-coinm/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMAggTrades(server: McpServer) { - server.tool( - "BinanceFuturesCOINMAggTrades", - "Get compressed, aggregate trades for a specific COIN-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - fromId: z.number().optional().describe("ID to get aggregate trades from INCLUSIVE"), - startTime: z.number().optional().describe("Timestamp in ms to get aggregate trades from INCLUSIVE"), - endTime: z.number().optional().describe("Timestamp in ms to get aggregate trades until INCLUSIVE"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMAggTrades", + { + description: "Get compressed, aggregate trades for a specific COIN-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + fromId: z.number().optional().describe("ID to get aggregate trades from INCLUSIVE"), + startTime: z + .number() + .optional() + .describe("Timestamp in ms to get aggregate trades from INCLUSIVE"), + endTime: z + .number() + .optional() + .describe("Timestamp in ms to get aggregate trades until INCLUSIVE"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.aggTrades(params); - const data = await deliveryClient.aggTrades(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} aggregated trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} aggregated trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures aggregated trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures aggregated trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/allOrders.ts b/src/tools/binance-futures-coinm/allOrders.ts index 26f44480..74bd1d11 100644 --- a/src/tools/binance-futures-coinm/allOrders.ts +++ b/src/tools/binance-futures-coinm/allOrders.ts @@ -1,51 +1,54 @@ // src/tools/binance-futures-coinm/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMAllOrders", - "Get all orders (active, canceled, or filled) for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), - orderId: z.number().optional().describe("Order ID to start from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, pair, orderId, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (pair) params.pair = pair; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMAllOrders", + { + description: "Get all orders (active, canceled, or filled) for COIN-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + orderId: z.number().optional().describe("Order ID to start from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, pair, orderId, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (pair) params.pair = pair; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; - const data = await deliveryClient.allOrders(params); - + const data = await deliveryClient.allOrders(params); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} COIN-M Futures orders. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures all orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} COIN-M Futures orders. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: [ + { type: "text", text: `Failed to retrieve COIN-M Futures all orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-futures-coinm/balance.ts b/src/tools/binance-futures-coinm/balance.ts index 4c461629..7e9f12a4 100644 --- a/src/tools/binance-futures-coinm/balance.ts +++ b/src/tools/binance-futures-coinm/balance.ts @@ -1,31 +1,36 @@ // src/tools/binance-futures-coinm/balance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMBalance(server: McpServer) { - server.tool( - "BinanceFuturesCOINMBalance", - "Get COIN-M futures account balance.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.getBalance({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M balance: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get COIN-M balance: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMBalance", + { + description: "Get COIN-M futures account balance.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.balance({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M balance: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get COIN-M balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/batchOrders.ts b/src/tools/binance-futures-coinm/batchOrders.ts index e78847a5..97ae8023 100644 --- a/src/tools/binance-futures-coinm/batchOrders.ts +++ b/src/tools/binance-futures-coinm/batchOrders.ts @@ -1,37 +1,45 @@ // src/tools/binance-futures-coinm/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMBatchOrders", - "Place multiple orders for COIN-M Futures (max 5 orders).", - { - batchOrders: z.string().describe("JSON string of order list. Max 5 orders. Each order has: symbol, side, type, and optional parameters") - }, - async ({ batchOrders }) => { - try { - const data = await deliveryClient.batchOrders({ batchOrders }); - + server.registerTool( + "BinanceFuturesCOINMBatchOrders", + { + description: "Place multiple orders for COIN-M Futures (max 5 orders).", + inputSchema: { + batchOrders: z + .string() + .describe( + "JSON string of order list. Max 5 orders. Each order has: symbol, side, type, and optional parameters", + ), + }, + }, + async ({ batchOrders }) => { + try { + const data = await deliveryClient.batchOrders({ batchOrders }); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures batch orders created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `COIN-M Futures batch orders created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create COIN-M Futures batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create COIN-M Futures batch orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/bookTicker.ts b/src/tools/binance-futures-coinm/bookTicker.ts index 991f6830..d4eebbd3 100644 --- a/src/tools/binance-futures-coinm/bookTicker.ts +++ b/src/tools/binance-futures-coinm/bookTicker.ts @@ -1,42 +1,55 @@ // src/tools/binance-futures-coinm/bookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMBookTicker(server: McpServer) { - server.tool( - "BinanceFuturesCOINMBookTicker", + server.registerTool( + "BinanceFuturesCOINMBookTicker", + { + description: "Get best price/qty on the order book for a symbol or symbols for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)") - }, - async ({ symbol, pair }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (pair) params.pair = pair; + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols", + ), + pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + }, + }, + async ({ symbol, pair }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (pair) params.pair = pair; + + const data = await deliveryClient.bookTicker(params); - const data = await deliveryClient.tickerBookTicker(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures book ticker${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures book ticker${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures book ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures book ticker: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/cancelAllOrders.ts b/src/tools/binance-futures-coinm/cancelAllOrders.ts index bf557e06..84d96cc5 100644 --- a/src/tools/binance-futures-coinm/cancelAllOrders.ts +++ b/src/tools/binance-futures-coinm/cancelAllOrders.ts @@ -1,33 +1,38 @@ // src/tools/binance-futures-coinm/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMCancelAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMCancelAllOrders", - "Cancel all open COIN-M futures orders for a symbol.", - { - symbol: z.string().describe("Trading symbol"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.cancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `All COIN-M orders cancelled: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel all COIN-M orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMCancelAllOrders", + { + description: "Cancel all open COIN-M futures orders for a symbol.", + inputSchema: { + symbol: z.string().describe("Trading symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.cancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `All COIN-M orders cancelled: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel all COIN-M orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/cancelBatchOrders.ts b/src/tools/binance-futures-coinm/cancelBatchOrders.ts index aba7a71a..cee5ac46 100644 --- a/src/tools/binance-futures-coinm/cancelBatchOrders.ts +++ b/src/tools/binance-futures-coinm/cancelBatchOrders.ts @@ -1,43 +1,50 @@ // src/tools/binance-futures-coinm/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMCancelBatchOrders", - "Cancel multiple orders for COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - orderIdList: z.string().optional().describe("Comma-separated list of order IDs (max 10)"), - origClientOrderIdList: z.string().optional().describe("Comma-separated list of client order IDs (max 10)") - }, - async ({ symbol, orderIdList, origClientOrderIdList }) => { - try { - const params: any = { symbol }; - if (orderIdList) params.orderIdList = orderIdList; - if (origClientOrderIdList) params.origClientOrderIdList = origClientOrderIdList; + server.registerTool( + "BinanceFuturesCOINMCancelBatchOrders", + { + description: "Cancel multiple orders for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + orderIdList: z.string().optional().describe("Comma-separated list of order IDs (max 10)"), + origClientOrderIdList: z + .string() + .optional() + .describe("Comma-separated list of client order IDs (max 10)"), + }, + }, + async ({ symbol, orderIdList, origClientOrderIdList }) => { + try { + const params: any = { symbol }; + if (orderIdList) params.orderIdList = orderIdList; + if (origClientOrderIdList) params.origClientOrderIdList = origClientOrderIdList; + + const data = await deliveryClient.cancelBatchOrders(params); - const data = await deliveryClient.cancelBatchOrders(params); - + return { + content: [ + { + type: "text", + text: `COIN-M Futures batch orders cancelled. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `COIN-M Futures batch orders cancelled. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel COIN-M Futures batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to cancel COIN-M Futures batch orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/cancelOrder.ts b/src/tools/binance-futures-coinm/cancelOrder.ts index 2a715ed6..52530b0c 100644 --- a/src/tools/binance-futures-coinm/cancelOrder.ts +++ b/src/tools/binance-futures-coinm/cancelOrder.ts @@ -1,37 +1,42 @@ // src/tools/binance-futures-coinm/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMCancelOrder(server: McpServer) { - server.tool( - "BinanceFuturesCOINMCancelOrder", - "Cancel a COIN-M futures order.", - { - symbol: z.string().describe("Trading symbol"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.cancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M order cancelled: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel COIN-M order: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMCancelOrder", + { + description: "Cancel a COIN-M futures order.", + inputSchema: { + symbol: z.string().describe("Trading symbol"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.cancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M order cancelled: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel COIN-M order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/commissionRate.ts b/src/tools/binance-futures-coinm/commissionRate.ts index 1698183c..aa7f198c 100644 --- a/src/tools/binance-futures-coinm/commissionRate.ts +++ b/src/tools/binance-futures-coinm/commissionRate.ts @@ -1,37 +1,44 @@ // src/tools/binance-futures-coinm/commissionRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMCommissionRate(server: McpServer) { - server.tool( - "BinanceFuturesCOINMCommissionRate", - "Get user commission rate for COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)") - }, - async ({ symbol }) => { - try { - const data = await deliveryClient.commissionRate({ symbol }); - + server.registerTool( + "BinanceFuturesCOINMCommissionRate", + { + description: "Get user commission rate for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + }, + }, + async ({ symbol }) => { + try { + const data = await deliveryClient.commissionRate({ symbol }); + + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures commission rate for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures commission rate for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures commission rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures commission rate: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/continuousKlines.ts b/src/tools/binance-futures-coinm/continuousKlines.ts index 57850e5e..54e044d4 100644 --- a/src/tools/binance-futures-coinm/continuousKlines.ts +++ b/src/tools/binance-futures-coinm/continuousKlines.ts @@ -1,49 +1,74 @@ // src/tools/binance-futures-coinm/continuousKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMContinuousKlines(server: McpServer) { - server.tool( - "BinanceFuturesCOINMContinuousKlines", - "Get continuous contract Kline/candlestick data for COIN-M Futures.", - { - pair: z.string().describe("Trading pair (e.g., BTCUSD)"), - contractType: z.enum(["PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]).describe("Contract type"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ pair, contractType, interval, startTime, endTime, limit }) => { - try { - const params: any = { pair, contractType, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMContinuousKlines", + { + description: "Get continuous contract Kline/candlestick data for COIN-M Futures.", + inputSchema: { + pair: z.string().describe("Trading pair (e.g., BTCUSD)"), + contractType: z + .enum(["PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]) + .describe("Contract type"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ pair, contractType, interval, startTime, endTime, limit }) => { + try { + const params: any = { pair, contractType, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.continuousKlines(params); - const data = await deliveryClient.continuousKlines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} continuous klines for COIN-M Futures ${pair} ${contractType} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} continuous klines for COIN-M Futures ${pair} ${contractType} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures continuous klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures continuous klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/depth.ts b/src/tools/binance-futures-coinm/depth.ts index d51a2a79..e89a5a50 100644 --- a/src/tools/binance-futures-coinm/depth.ts +++ b/src/tools/binance-futures-coinm/depth.ts @@ -1,41 +1,53 @@ // src/tools/binance-futures-coinm/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMDepth(server: McpServer) { - server.tool( - "BinanceFuturesCOINMDepth", - "Get order book depth data for a specific COIN-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - limit: z.number().optional().describe("Depth of the order book. Default 500; max 1000. Valid limits: [5, 10, 20, 50, 100, 500, 1000]") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMDepth", + { + description: "Get order book depth data for a specific COIN-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + limit: z + .number() + .optional() + .describe( + "Depth of the order book. Default 500; max 1000. Valid limits: [5, 10, 20, 50, 100, 500, 1000]", + ), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.depth(params); - const data = await deliveryClient.depth(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures order book depth: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures order book depth: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/exchangeInfo.ts b/src/tools/binance-futures-coinm/exchangeInfo.ts index db6709c3..f431af75 100644 --- a/src/tools/binance-futures-coinm/exchangeInfo.ts +++ b/src/tools/binance-futures-coinm/exchangeInfo.ts @@ -1,33 +1,36 @@ // src/tools/binance-futures-coinm/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMExchangeInfo(server: McpServer) { - server.tool( - "BinanceFuturesCOINMExchangeInfo", - "Get current exchange trading rules and symbol information for COIN-M Futures.", - {}, - async () => { - try { - const data = await deliveryClient.exchangeInfo(); - - return { - content: [ - { - type: "text", - text: `COIN-M Futures exchange info retrieved. Symbols count: ${data.symbols?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get COIN-M Futures exchange info: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMExchangeInfo", + { + description: "Get current exchange trading rules and symbol information for COIN-M Futures.", + }, + async () => { + try { + const data = await deliveryClient.exchangeInfo(); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures exchange info retrieved. Symbols count: ${data.symbols?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get COIN-M Futures exchange info: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/forceOrders.ts b/src/tools/binance-futures-coinm/forceOrders.ts index ed563c1f..4b956f55 100644 --- a/src/tools/binance-futures-coinm/forceOrders.ts +++ b/src/tools/binance-futures-coinm/forceOrders.ts @@ -1,48 +1,58 @@ // src/tools/binance-futures-coinm/forceOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMForceOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMForceOrders", - "Get user force orders (liquidation orders) for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("Auto close type: LIQUIDATION or ADL"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 50; max 100") - }, - async ({ symbol, autoCloseType, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (autoCloseType) params.autoCloseType = autoCloseType; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMForceOrders", + { + description: "Get user force orders (liquidation orders) for COIN-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + autoCloseType: z + .enum(["LIQUIDATION", "ADL"]) + .optional() + .describe("Auto close type: LIQUIDATION or ADL"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 50; max 100"), + }, + }, + async ({ symbol, autoCloseType, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (autoCloseType) params.autoCloseType = autoCloseType; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.forceOrders(params); - const data = await deliveryClient.forceOrders(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} COIN-M Futures force orders. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} COIN-M Futures force orders. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures force orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures force orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/fundingRate.ts b/src/tools/binance-futures-coinm/fundingRate.ts index 880fd15c..24f62e3b 100644 --- a/src/tools/binance-futures-coinm/fundingRate.ts +++ b/src/tools/binance-futures-coinm/fundingRate.ts @@ -1,46 +1,53 @@ // src/tools/binance-futures-coinm/fundingRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMFundingRate(server: McpServer) { - server.tool( - "BinanceFuturesCOINMFundingRate", - "Get funding rate history for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 100; max 1000") - }, - async ({ symbol, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMFundingRate", + { + description: "Get funding rate history for COIN-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 100; max 1000"), + }, + }, + async ({ symbol, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.fundingRate(params); - const data = await deliveryClient.fundingRate(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} funding rate records for COIN-M Futures${symbol ? ` ${symbol}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} funding rate records for COIN-M Futures${symbol ? ` ${symbol}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures funding rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures funding rate: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/getOrder.ts b/src/tools/binance-futures-coinm/getOrder.ts index b529445d..dd25d9d3 100644 --- a/src/tools/binance-futures-coinm/getOrder.ts +++ b/src/tools/binance-futures-coinm/getOrder.ts @@ -1,37 +1,42 @@ // src/tools/binance-futures-coinm/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMGetOrder(server: McpServer) { - server.tool( - "BinanceFuturesCOINMGetOrder", - "Query a COIN-M futures order.", - { - symbol: z.string().describe("Trading symbol"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.getOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M order: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get COIN-M order: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMGetOrder", + { + description: "Query a COIN-M futures order.", + inputSchema: { + symbol: z.string().describe("Trading symbol"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.getOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M order: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get COIN-M order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/historicalTrades.ts b/src/tools/binance-futures-coinm/historicalTrades.ts index bf366215..d30785c7 100644 --- a/src/tools/binance-futures-coinm/historicalTrades.ts +++ b/src/tools/binance-futures-coinm/historicalTrades.ts @@ -1,43 +1,53 @@ // src/tools/binance-futures-coinm/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMHistoricalTrades(server: McpServer) { - server.tool( - "BinanceFuturesCOINMHistoricalTrades", - "Get older market historical trades for a specific COIN-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), - fromId: z.number().optional().describe("Trade ID to fetch from. Default gets most recent trades") - }, - async ({ symbol, limit, fromId }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - if (fromId !== undefined) params.fromId = fromId; + server.registerTool( + "BinanceFuturesCOINMHistoricalTrades", + { + description: "Get older market historical trades for a specific COIN-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), + fromId: z + .number() + .optional() + .describe("Trade ID to fetch from. Default gets most recent trades"), + }, + }, + async ({ symbol, limit, fromId }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + if (fromId !== undefined) params.fromId = fromId; + + const data = await deliveryClient.historicalTrades(params); - const data = await deliveryClient.historicalTrades(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} historical trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} historical trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures historical trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures historical trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/income.ts b/src/tools/binance-futures-coinm/income.ts index a2925850..4b3a9eaf 100644 --- a/src/tools/binance-futures-coinm/income.ts +++ b/src/tools/binance-futures-coinm/income.ts @@ -1,48 +1,67 @@ // src/tools/binance-futures-coinm/income.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMIncome(server: McpServer) { - server.tool( - "BinanceFuturesCOINMIncome", - "Get income history for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - incomeType: z.enum(["TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", "COMMISSION", "INSURANCE_CLEAR", "REFERRAL_KICKBACK", "COMMISSION_REBATE", "DELIVERED_SETTELMENT", "COIN_SWAP_DEPOSIT", "COIN_SWAP_WITHDRAW"]).optional().describe("Income type"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 100; max 1000") - }, - async ({ symbol, incomeType, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (incomeType) params.incomeType = incomeType; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMIncome", + { + description: "Get income history for COIN-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + incomeType: z + .enum([ + "TRANSFER", + "WELCOME_BONUS", + "REALIZED_PNL", + "FUNDING_FEE", + "COMMISSION", + "INSURANCE_CLEAR", + "REFERRAL_KICKBACK", + "COMMISSION_REBATE", + "DELIVERED_SETTELMENT", + "COIN_SWAP_DEPOSIT", + "COIN_SWAP_WITHDRAW", + ]) + .optional() + .describe("Income type"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 100; max 1000"), + }, + }, + async ({ symbol, incomeType, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (incomeType) params.incomeType = incomeType; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.income(params); - const data = await deliveryClient.income(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} COIN-M Futures income records. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} COIN-M Futures income records. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures income: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve COIN-M Futures income: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/index.ts b/src/tools/binance-futures-coinm/index.ts index 5d4d0755..04f66887 100644 --- a/src/tools/binance-futures-coinm/index.ts +++ b/src/tools/binance-futures-coinm/index.ts @@ -1,94 +1,96 @@ // src/tools/binance-futures-coinm/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; - -// Market Data -import { registerBinanceFuturesCOINMPing } from "./ping.js"; -import { registerBinanceFuturesCOINMTime } from "./time.js"; -import { registerBinanceFuturesCOINMExchangeInfo } from "./exchangeInfo.js"; -import { registerBinanceFuturesCOINMDepth } from "./depth.js"; -import { registerBinanceFuturesCOINMTrades } from "./trades.js"; -import { registerBinanceFuturesCOINMHistoricalTrades } from "./historicalTrades.js"; -import { registerBinanceFuturesCOINMAggTrades } from "./aggTrades.js"; -import { registerBinanceFuturesCOINMKlines } from "./klines.js"; -import { registerBinanceFuturesCOINMContinuousKlines } from "./continuousKlines.js"; -import { registerBinanceFuturesCOINMIndexPriceKlines } from "./indexPriceKlines.js"; -import { registerBinanceFuturesCOINMMarkPriceKlines } from "./markPriceKlines.js"; -import { registerBinanceFuturesCOINMPremiumIndex } from "./premiumIndex.js"; -import { registerBinanceFuturesCOINMFundingRate } from "./fundingRate.js"; -import { registerBinanceFuturesCOINMTicker24hr } from "./ticker24hr.js"; -import { registerBinanceFuturesCOINMTickerPrice } from "./tickerPrice.js"; -import { registerBinanceFuturesCOINMBookTicker } from "./bookTicker.js"; -import { registerBinanceFuturesCOINMOpenInterest } from "./openInterest.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; // Account & Trading import { registerBinanceFuturesCOINMAccount } from "./account.js"; +import { registerBinanceFuturesCOINMADLQuantile } from "./adlQuantile.js"; +import { registerBinanceFuturesCOINMAggTrades } from "./aggTrades.js"; +import { registerBinanceFuturesCOINMAllOrders } from "./allOrders.js"; import { registerBinanceFuturesCOINMBalance } from "./balance.js"; -import { registerBinanceFuturesCOINMPositionRisk } from "./positionRisk.js"; -import { registerBinanceFuturesCOINMNewOrder } from "./newOrder.js"; import { registerBinanceFuturesCOINMBatchOrders } from "./batchOrders.js"; -import { registerBinanceFuturesCOINMGetOrder } from "./getOrder.js"; -import { registerBinanceFuturesCOINMCancelOrder } from "./cancelOrder.js"; +import { registerBinanceFuturesCOINMBookTicker } from "./bookTicker.js"; import { registerBinanceFuturesCOINMCancelAllOrders } from "./cancelAllOrders.js"; import { registerBinanceFuturesCOINMCancelBatchOrders } from "./cancelBatchOrders.js"; -import { registerBinanceFuturesCOINMOpenOrders } from "./openOrders.js"; -import { registerBinanceFuturesCOINMAllOrders } from "./allOrders.js"; -import { registerBinanceFuturesCOINMUserTrades } from "./userTrades.js"; +import { registerBinanceFuturesCOINMCancelOrder } from "./cancelOrder.js"; +import { registerBinanceFuturesCOINMCommissionRate } from "./commissionRate.js"; +import { registerBinanceFuturesCOINMContinuousKlines } from "./continuousKlines.js"; +import { registerBinanceFuturesCOINMDepth } from "./depth.js"; +import { registerBinanceFuturesCOINMExchangeInfo } from "./exchangeInfo.js"; +import { registerBinanceFuturesCOINMForceOrders } from "./forceOrders.js"; +import { registerBinanceFuturesCOINMFundingRate } from "./fundingRate.js"; +import { registerBinanceFuturesCOINMGetOrder } from "./getOrder.js"; +import { registerBinanceFuturesCOINMHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceFuturesCOINMIncome } from "./income.js"; +import { registerBinanceFuturesCOINMIndexPriceKlines } from "./indexPriceKlines.js"; +import { registerBinanceFuturesCOINMKlines } from "./klines.js"; import { registerBinanceFuturesCOINMLeverage } from "./leverage.js"; +// User Data Stream +import { + registerBinanceFuturesCOINMListenKeyClose, + registerBinanceFuturesCOINMListenKeyCreate, + registerBinanceFuturesCOINMListenKeyRenew, +} from "./listenKey.js"; import { registerBinanceFuturesCOINMMarginType } from "./marginType.js"; +import { registerBinanceFuturesCOINMMarkPriceKlines } from "./markPriceKlines.js"; +import { registerBinanceFuturesCOINMNewOrder } from "./newOrder.js"; +import { registerBinanceFuturesCOINMOpenInterest } from "./openInterest.js"; +import { registerBinanceFuturesCOINMOpenOrders } from "./openOrders.js"; +// Market Data +import { registerBinanceFuturesCOINMPing } from "./ping.js"; import { registerBinanceFuturesCOINMPositionMargin } from "./positionMargin.js"; import { registerBinanceFuturesCOINMPositionMode } from "./positionMode.js"; -import { registerBinanceFuturesCOINMCommissionRate } from "./commissionRate.js"; -import { registerBinanceFuturesCOINMForceOrders } from "./forceOrders.js"; -import { registerBinanceFuturesCOINMADLQuantile } from "./adlQuantile.js"; - -// User Data Stream -import { registerBinanceFuturesCOINMListenKeyCreate, registerBinanceFuturesCOINMListenKeyRenew, registerBinanceFuturesCOINMListenKeyClose } from "./listenKey.js"; +import { registerBinanceFuturesCOINMPositionRisk } from "./positionRisk.js"; +import { registerBinanceFuturesCOINMPremiumIndex } from "./premiumIndex.js"; +import { registerBinanceFuturesCOINMTicker24hr } from "./ticker24hr.js"; +import { registerBinanceFuturesCOINMTickerPrice } from "./tickerPrice.js"; +import { registerBinanceFuturesCOINMTime } from "./time.js"; +import { registerBinanceFuturesCOINMTrades } from "./trades.js"; +import { registerBinanceFuturesCOINMUserTrades } from "./userTrades.js"; export function registerBinanceFuturesCOINMTools(server: McpServer) { - // Market Data - registerBinanceFuturesCOINMPing(server); - registerBinanceFuturesCOINMTime(server); - registerBinanceFuturesCOINMExchangeInfo(server); - registerBinanceFuturesCOINMDepth(server); - registerBinanceFuturesCOINMTrades(server); - registerBinanceFuturesCOINMHistoricalTrades(server); - registerBinanceFuturesCOINMAggTrades(server); - registerBinanceFuturesCOINMKlines(server); - registerBinanceFuturesCOINMContinuousKlines(server); - registerBinanceFuturesCOINMIndexPriceKlines(server); - registerBinanceFuturesCOINMMarkPriceKlines(server); - registerBinanceFuturesCOINMPremiumIndex(server); - registerBinanceFuturesCOINMFundingRate(server); - registerBinanceFuturesCOINMTicker24hr(server); - registerBinanceFuturesCOINMTickerPrice(server); - registerBinanceFuturesCOINMBookTicker(server); - registerBinanceFuturesCOINMOpenInterest(server); + // Market Data + registerBinanceFuturesCOINMPing(server); + registerBinanceFuturesCOINMTime(server); + registerBinanceFuturesCOINMExchangeInfo(server); + registerBinanceFuturesCOINMDepth(server); + registerBinanceFuturesCOINMTrades(server); + registerBinanceFuturesCOINMHistoricalTrades(server); + registerBinanceFuturesCOINMAggTrades(server); + registerBinanceFuturesCOINMKlines(server); + registerBinanceFuturesCOINMContinuousKlines(server); + registerBinanceFuturesCOINMIndexPriceKlines(server); + registerBinanceFuturesCOINMMarkPriceKlines(server); + registerBinanceFuturesCOINMPremiumIndex(server); + registerBinanceFuturesCOINMFundingRate(server); + registerBinanceFuturesCOINMTicker24hr(server); + registerBinanceFuturesCOINMTickerPrice(server); + registerBinanceFuturesCOINMBookTicker(server); + registerBinanceFuturesCOINMOpenInterest(server); - // Account & Trading - registerBinanceFuturesCOINMAccount(server); - registerBinanceFuturesCOINMBalance(server); - registerBinanceFuturesCOINMPositionRisk(server); - registerBinanceFuturesCOINMNewOrder(server); - registerBinanceFuturesCOINMBatchOrders(server); - registerBinanceFuturesCOINMGetOrder(server); - registerBinanceFuturesCOINMCancelOrder(server); - registerBinanceFuturesCOINMCancelAllOrders(server); - registerBinanceFuturesCOINMCancelBatchOrders(server); - registerBinanceFuturesCOINMOpenOrders(server); - registerBinanceFuturesCOINMAllOrders(server); - registerBinanceFuturesCOINMUserTrades(server); - registerBinanceFuturesCOINMIncome(server); - registerBinanceFuturesCOINMLeverage(server); - registerBinanceFuturesCOINMMarginType(server); - registerBinanceFuturesCOINMPositionMargin(server); - registerBinanceFuturesCOINMPositionMode(server); - registerBinanceFuturesCOINMCommissionRate(server); - registerBinanceFuturesCOINMForceOrders(server); - registerBinanceFuturesCOINMADLQuantile(server); + // Account & Trading + registerBinanceFuturesCOINMAccount(server); + registerBinanceFuturesCOINMBalance(server); + registerBinanceFuturesCOINMPositionRisk(server); + registerBinanceFuturesCOINMNewOrder(server); + registerBinanceFuturesCOINMBatchOrders(server); + registerBinanceFuturesCOINMGetOrder(server); + registerBinanceFuturesCOINMCancelOrder(server); + registerBinanceFuturesCOINMCancelAllOrders(server); + registerBinanceFuturesCOINMCancelBatchOrders(server); + registerBinanceFuturesCOINMOpenOrders(server); + registerBinanceFuturesCOINMAllOrders(server); + registerBinanceFuturesCOINMUserTrades(server); + registerBinanceFuturesCOINMIncome(server); + registerBinanceFuturesCOINMLeverage(server); + registerBinanceFuturesCOINMMarginType(server); + registerBinanceFuturesCOINMPositionMargin(server); + registerBinanceFuturesCOINMPositionMode(server); + registerBinanceFuturesCOINMCommissionRate(server); + registerBinanceFuturesCOINMForceOrders(server); + registerBinanceFuturesCOINMADLQuantile(server); - // User Data Stream - registerBinanceFuturesCOINMListenKeyCreate(server); - registerBinanceFuturesCOINMListenKeyRenew(server); - registerBinanceFuturesCOINMListenKeyClose(server); + // User Data Stream + registerBinanceFuturesCOINMListenKeyCreate(server); + registerBinanceFuturesCOINMListenKeyRenew(server); + registerBinanceFuturesCOINMListenKeyClose(server); } diff --git a/src/tools/binance-futures-coinm/indexPriceKlines.ts b/src/tools/binance-futures-coinm/indexPriceKlines.ts index 656f10ff..a6291ce0 100644 --- a/src/tools/binance-futures-coinm/indexPriceKlines.ts +++ b/src/tools/binance-futures-coinm/indexPriceKlines.ts @@ -1,48 +1,71 @@ // src/tools/binance-futures-coinm/indexPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMIndexPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesCOINMIndexPriceKlines", - "Get index price Kline/candlestick data for COIN-M Futures.", - { - pair: z.string().describe("Trading pair (e.g., BTCUSD)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ pair, interval, startTime, endTime, limit }) => { - try { - const params: any = { pair, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMIndexPriceKlines", + { + description: "Get index price Kline/candlestick data for COIN-M Futures.", + inputSchema: { + pair: z.string().describe("Trading pair (e.g., BTCUSD)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ pair, interval, startTime, endTime, limit }) => { + try { + const params: any = { pair, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.indexPriceKlines(params); - const data = await deliveryClient.indexPriceKlines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} index price klines for COIN-M Futures ${pair} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} index price klines for COIN-M Futures ${pair} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures index price klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures index price klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/klines.ts b/src/tools/binance-futures-coinm/klines.ts index aa440b0f..e2eca7a1 100644 --- a/src/tools/binance-futures-coinm/klines.ts +++ b/src/tools/binance-futures-coinm/klines.ts @@ -1,48 +1,68 @@ // src/tools/binance-futures-coinm/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMKlines(server: McpServer) { - server.tool( - "BinanceFuturesCOINMKlines", - "Get Kline/candlestick bars for a specific COIN-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMKlines", + { + description: "Get Kline/candlestick bars for a specific COIN-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.klines(params); - const data = await deliveryClient.klines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} klines for COIN-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} klines for COIN-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve COIN-M Futures klines: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/leverage.ts b/src/tools/binance-futures-coinm/leverage.ts index f422613e..e03928c7 100644 --- a/src/tools/binance-futures-coinm/leverage.ts +++ b/src/tools/binance-futures-coinm/leverage.ts @@ -1,35 +1,40 @@ // src/tools/binance-futures-coinm/leverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMLeverage(server: McpServer) { - server.tool( - "BinanceFuturesCOINMLeverage", - "Change initial leverage for COIN-M futures symbol.", - { - symbol: z.string().describe("Trading symbol"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.changeInitialLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M leverage changed: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to change COIN-M leverage: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMLeverage", + { + description: "Change initial leverage for COIN-M futures symbol.", + inputSchema: { + symbol: z.string().describe("Trading symbol"), + leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.leverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M leverage changed: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to change COIN-M leverage: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/listenKey.ts b/src/tools/binance-futures-coinm/listenKey.ts index eb0ffe21..a7226e7d 100644 --- a/src/tools/binance-futures-coinm/listenKey.ts +++ b/src/tools/binance-futures-coinm/listenKey.ts @@ -1,96 +1,97 @@ // src/tools/binance-futures-coinm/listenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMListenKeyCreate(server: McpServer) { - server.tool( - "BinanceFuturesCOINMListenKeyCreate", + server.registerTool( + "BinanceFuturesCOINMListenKeyCreate", + { + description: "Start a new user data stream for COIN-M Futures. Returns a listenKey for WebSocket connection.", - {}, - async () => { - try { - const data = await deliveryClient.createListenKey(); - + }, + async () => { + try { + const data = await deliveryClient.createListenKey(); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures listen key created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `COIN-M Futures listen key created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create COIN-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create COIN-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } export function registerBinanceFuturesCOINMListenKeyRenew(server: McpServer) { - server.tool( - "BinanceFuturesCOINMListenKeyRenew", - "Keepalive a user data stream to prevent timeout for COIN-M Futures.", - {}, - async () => { - try { - const data = await deliveryClient.keepAliveListenKey(); - + server.registerTool( + "BinanceFuturesCOINMListenKeyRenew", + { description: "Keepalive a user data stream to prevent timeout for COIN-M Futures." }, + async () => { + try { + const data = await deliveryClient.keepAliveListenKey(); - return { - content: [ - { - type: "text", - text: `COIN-M Futures listen key renewed. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to renew COIN-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `COIN-M Futures listen key renewed. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to renew COIN-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } export function registerBinanceFuturesCOINMListenKeyClose(server: McpServer) { - server.tool( - "BinanceFuturesCOINMListenKeyClose", - "Close a user data stream for COIN-M Futures.", - {}, - async () => { - try { - const data = await deliveryClient.closeListenKey(); - + server.registerTool( + "BinanceFuturesCOINMListenKeyClose", + { description: "Close a user data stream for COIN-M Futures." }, + async () => { + try { + const data = await deliveryClient.closeListenKey(); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures listen key closed. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `COIN-M Futures listen key closed. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to close COIN-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to close COIN-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/marginType.ts b/src/tools/binance-futures-coinm/marginType.ts index 96c0d318..d2056dd6 100644 --- a/src/tools/binance-futures-coinm/marginType.ts +++ b/src/tools/binance-futures-coinm/marginType.ts @@ -1,39 +1,42 @@ // src/tools/binance-futures-coinm/marginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMMarginType(server: McpServer) { - server.tool( - "BinanceFuturesCOINMMarginType", - "Change margin type for a symbol in COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED") - }, - async ({ symbol, marginType }) => { - try { - const data = await deliveryClient.marginType({ symbol, marginType }); - + server.registerTool( + "BinanceFuturesCOINMMarginType", + { + description: "Change margin type for a symbol in COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED"), + }, + }, + async ({ symbol, marginType }) => { + try { + const data = await deliveryClient.marginType({ symbol, marginType }); - return { - content: [ - { - type: "text", - text: `COIN-M Futures margin type changed to ${marginType} for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change COIN-M Futures margin type: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} + return { + content: [ + { + type: "text", + text: `COIN-M Futures margin type changed to ${marginType} for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: [ + { type: "text", text: `Failed to change COIN-M Futures margin type: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-futures-coinm/markPriceKlines.ts b/src/tools/binance-futures-coinm/markPriceKlines.ts index adf46edd..90b6cbc6 100644 --- a/src/tools/binance-futures-coinm/markPriceKlines.ts +++ b/src/tools/binance-futures-coinm/markPriceKlines.ts @@ -1,48 +1,71 @@ // src/tools/binance-futures-coinm/markPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMMarkPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesCOINMMarkPriceKlines", - "Get mark price Kline/candlestick data for COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMMarkPriceKlines", + { + description: "Get mark price Kline/candlestick data for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.markPriceKlines(params); - const data = await deliveryClient.markPriceKlines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} mark price klines for COIN-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} mark price klines for COIN-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures mark price klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures mark price klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/aggTrades.ts b/src/tools/binance-futures-coinm/market-api/aggTrades.ts index e8569751..95f81634 100644 --- a/src/tools/binance-futures-coinm/market-api/aggTrades.ts +++ b/src/tools/binance-futures-coinm/market-api/aggTrades.ts @@ -5,46 +5,54 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryAggTrades(server: McpServer) { - server.tool( - "BinanceDeliveryAggTrades", + server.registerTool( + "BinanceDeliveryAggTrades", + { + description: "Get compressed/aggregate trades for a COIN-M Futures symbol. Trades that fill at the same time, from the same order, with the same price will be aggregated.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - fromId: z.number().int().optional().describe("ID to get aggregate trades from INCLUSIVE"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.aggTrades({ - symbol: params.symbol, - ...(params.fromId && { fromId: params.fromId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Aggregate Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get aggregate trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + fromId: z.number().int().optional().describe("ID to get aggregate trades from INCLUSIVE"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.aggTrades({ + symbol: params.symbol, + ...(params.fromId && { fromId: params.fromId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Aggregate Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get aggregate trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/bookTicker.ts b/src/tools/binance-futures-coinm/market-api/bookTicker.ts index 1e66e306..db0e45e2 100644 --- a/src/tools/binance-futures-coinm/market-api/bookTicker.ts +++ b/src/tools/binance-futures-coinm/market-api/bookTicker.ts @@ -5,40 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/bookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryTickerBookTicker(server: McpServer) { - server.tool( - "BinanceDeliveryTickerBookTicker", - "Get best bid/ask price and quantity for COIN-M Futures symbol(s).", - { - symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.tickerBookTicker({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📖 Book Ticker${params.symbol ? ` for ${params.symbol}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get book ticker: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryTickerBookTicker", + { + description: "Get best bid/ask price and quantity for COIN-M Futures symbol(s).", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), + pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.tickerBookTicker({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📖 Book Ticker${params.symbol ? ` for ${params.symbol}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get book ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/continuousKlines.ts b/src/tools/binance-futures-coinm/market-api/continuousKlines.ts index 393f8bad..87cc354b 100644 --- a/src/tools/binance-futures-coinm/market-api/continuousKlines.ts +++ b/src/tools/binance-futures-coinm/market-api/continuousKlines.ts @@ -5,52 +5,76 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/continuousKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryContinuousKlines(server: McpServer) { - server.tool( - "BinanceDeliveryContinuousKlines", + server.registerTool( + "BinanceDeliveryContinuousKlines", + { + description: "Get continuous contract kline/candlestick data for a COIN-M Futures pair. Continuous contract uses the price of the current delivery period contract.", - { - pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), - contractType: z.enum(["PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]).describe("Contract type"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.continuousKlines({ - pair: params.pair, - contractType: params.contractType, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `🕯️ Continuous Klines for ${params.pair} ${params.contractType} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get continuous klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), + contractType: z + .enum(["PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]) + .describe("Contract type"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.continuousKlines({ + pair: params.pair, + contractType: params.contractType, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `🕯️ Continuous Klines for ${params.pair} ${params.contractType} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get continuous klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/depth.ts b/src/tools/binance-futures-coinm/market-api/depth.ts index 94bdfd6f..e246c4d3 100644 --- a/src/tools/binance-futures-coinm/market-api/depth.ts +++ b/src/tools/binance-futures-coinm/market-api/depth.ts @@ -5,40 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryDepth(server: McpServer) { - server.tool( - "BinanceDeliveryDepth", - "Get COIN-M Futures order book depth for a symbol.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP, BTCUSD_230630)"), - limit: z.number().int().optional().describe("Depth limit: 5, 10, 20, 50, 100, 500, 1000 (default 500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.depth({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📚 Order Book for ${params.symbol}\n\nLast Update ID: ${data.lastUpdateId}\nBids: ${data.bids?.length || 0}\nAsks: ${data.asks?.length || 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get order book: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryDepth", + { + description: "Get COIN-M Futures order book depth for a symbol.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP, BTCUSD_230630)"), + limit: z + .number() + .int() + .optional() + .describe("Depth limit: 5, 10, 20, 50, 100, 500, 1000 (default 500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.depth({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📚 Order Book for ${params.symbol}\n\nLast Update ID: ${data.lastUpdateId}\nBids: ${data.bids?.length || 0}\nAsks: ${data.asks?.length || 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get order book: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/exchangeInfo.ts b/src/tools/binance-futures-coinm/market-api/exchangeInfo.ts index f5fb6341..d884c6cd 100644 --- a/src/tools/binance-futures-coinm/market-api/exchangeInfo.ts +++ b/src/tools/binance-futures-coinm/market-api/exchangeInfo.ts @@ -5,34 +5,40 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../../config/binanceClient.js"; export function registerBinanceDeliveryExchangeInfo(server: McpServer) { - server.tool( - "BinanceDeliveryExchangeInfo", + server.registerTool( + "BinanceDeliveryExchangeInfo", + { + description: "Get COIN-M Futures exchange information including trading rules, symbol info, and rate limits.", - {}, - async () => { - try { - const response = await deliveryClient.restAPI.exchangeInfo(); - const data = await response.data(); - - const symbolCount = data.symbols?.length || 0; - - return { - content: [{ - type: "text", - text: `📊 COIN-M Futures Exchange Info\n\nTimezone: ${data.timezone}\nServer Time: ${new Date(data.serverTime).toISOString()}\nTotal Symbols: ${symbolCount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get exchange info: ${errorMessage}` }], - isError: true - }; - } - } - ); + }, + async () => { + try { + const response = await deliveryClient.restAPI.exchangeInfo(); + const data = await response.data(); + + const symbolCount = data.symbols?.length || 0; + + return { + content: [ + { + type: "text", + text: `📊 COIN-M Futures Exchange Info\n\nTimezone: ${data.timezone}\nServer Time: ${new Date(data.serverTime).toISOString()}\nTotal Symbols: ${symbolCount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get exchange info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/fundingRate.ts b/src/tools/binance-futures-coinm/market-api/fundingRate.ts index b91749e0..20a10d37 100644 --- a/src/tools/binance-futures-coinm/market-api/fundingRate.ts +++ b/src/tools/binance-futures-coinm/market-api/fundingRate.ts @@ -5,44 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/fundingRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryFundingRate(server: McpServer) { - server.tool( - "BinanceDeliveryFundingRate", - "Get funding rate history for a COIN-M Futures perpetual contract.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 100, max 1000)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.fundingRate({ - symbol: params.symbol, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Funding Rate History for ${params.symbol}\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get funding rate: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryFundingRate", + { + description: "Get funding rate history for a COIN-M Futures perpetual contract.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 100, max 1000)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.fundingRate({ + symbol: params.symbol, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Funding Rate History for ${params.symbol}\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get funding rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/historicalTrades.ts b/src/tools/binance-futures-coinm/market-api/historicalTrades.ts index 1a82fcdc..a1d62e94 100644 --- a/src/tools/binance-futures-coinm/market-api/historicalTrades.ts +++ b/src/tools/binance-futures-coinm/market-api/historicalTrades.ts @@ -5,42 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryHistoricalTrades(server: McpServer) { - server.tool( - "BinanceDeliveryHistoricalTrades", + server.registerTool( + "BinanceDeliveryHistoricalTrades", + { + description: "Get older market historical trades for a COIN-M Futures symbol. Requires API key.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)"), - fromId: z.number().int().optional().describe("Trade ID to fetch from (older trades)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.historicalTrades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }), - ...(params.fromId && { fromId: params.fromId }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📜 Historical Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get historical trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)"), + fromId: z.number().int().optional().describe("Trade ID to fetch from (older trades)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.historicalTrades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + ...(params.fromId && { fromId: params.fromId }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📜 Historical Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get historical trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/index.ts b/src/tools/binance-futures-coinm/market-api/index.ts index 04119655..0bd4212c 100644 --- a/src/tools/binance-futures-coinm/market-api/index.ts +++ b/src/tools/binance-futures-coinm/market-api/index.ts @@ -5,54 +5,55 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDeliveryPing } from "./ping.js"; -import { registerBinanceDeliveryTime } from "./time.js"; -import { registerBinanceDeliveryExchangeInfo } from "./exchangeInfo.js"; -import { registerBinanceDeliveryDepth } from "./depth.js"; -import { registerBinanceDeliveryTrades } from "./trades.js"; -import { registerBinanceDeliveryHistoricalTrades } from "./historicalTrades.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDeliveryAggTrades } from "./aggTrades.js"; -import { registerBinanceDeliveryKlines } from "./klines.js"; +import { registerBinanceDeliveryTickerBookTicker } from "./bookTicker.js"; import { registerBinanceDeliveryContinuousKlines } from "./continuousKlines.js"; +import { registerBinanceDeliveryDepth } from "./depth.js"; +import { registerBinanceDeliveryExchangeInfo } from "./exchangeInfo.js"; +import { registerBinanceDeliveryFundingRate } from "./fundingRate.js"; +import { registerBinanceDeliveryHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceDeliveryIndexPriceKlines } from "./indexPriceKlines.js"; +import { registerBinanceDeliveryKlines } from "./klines.js"; import { registerBinanceDeliveryMarkPriceKlines } from "./markPriceKlines.js"; +import { registerBinanceDeliveryOpenInterest } from "./openInterest.js"; +import { registerBinanceDeliveryOpenInterestHist } from "./openInterestHist.js"; +import { registerBinanceDeliveryPing } from "./ping.js"; import { registerBinanceDeliveryPremiumIndex } from "./premiumIndex.js"; -import { registerBinanceDeliveryFundingRate } from "./fundingRate.js"; import { registerBinanceDelivery24hrTicker } from "./ticker24hr.js"; import { registerBinanceDeliveryTickerPrice } from "./tickerPrice.js"; -import { registerBinanceDeliveryTickerBookTicker } from "./bookTicker.js"; -import { registerBinanceDeliveryOpenInterest } from "./openInterest.js"; -import { registerBinanceDeliveryOpenInterestHist } from "./openInterestHist.js"; +import { registerBinanceDeliveryTime } from "./time.js"; +import { registerBinanceDeliveryTrades } from "./trades.js"; export function registerBinanceDeliveryMarketApiTools(server: McpServer) { - // System Status - registerBinanceDeliveryPing(server); - registerBinanceDeliveryTime(server); - registerBinanceDeliveryExchangeInfo(server); - - // Order Book & Trades - registerBinanceDeliveryDepth(server); - registerBinanceDeliveryTrades(server); - registerBinanceDeliveryHistoricalTrades(server); - registerBinanceDeliveryAggTrades(server); - - // Klines/Candlesticks - registerBinanceDeliveryKlines(server); - registerBinanceDeliveryContinuousKlines(server); - registerBinanceDeliveryIndexPriceKlines(server); - registerBinanceDeliveryMarkPriceKlines(server); - - // Pricing & Funding - registerBinanceDeliveryPremiumIndex(server); - registerBinanceDeliveryFundingRate(server); - - // Tickers - registerBinanceDelivery24hrTicker(server); - registerBinanceDeliveryTickerPrice(server); - registerBinanceDeliveryTickerBookTicker(server); - - // Open Interest - registerBinanceDeliveryOpenInterest(server); - registerBinanceDeliveryOpenInterestHist(server); + // System Status + registerBinanceDeliveryPing(server); + registerBinanceDeliveryTime(server); + registerBinanceDeliveryExchangeInfo(server); + + // Order Book & Trades + registerBinanceDeliveryDepth(server); + registerBinanceDeliveryTrades(server); + registerBinanceDeliveryHistoricalTrades(server); + registerBinanceDeliveryAggTrades(server); + + // Klines/Candlesticks + registerBinanceDeliveryKlines(server); + registerBinanceDeliveryContinuousKlines(server); + registerBinanceDeliveryIndexPriceKlines(server); + registerBinanceDeliveryMarkPriceKlines(server); + + // Pricing & Funding + registerBinanceDeliveryPremiumIndex(server); + registerBinanceDeliveryFundingRate(server); + + // Tickers + registerBinanceDelivery24hrTicker(server); + registerBinanceDeliveryTickerPrice(server); + registerBinanceDeliveryTickerBookTicker(server); + + // Open Interest + registerBinanceDeliveryOpenInterest(server); + registerBinanceDeliveryOpenInterestHist(server); } diff --git a/src/tools/binance-futures-coinm/market-api/indexPriceKlines.ts b/src/tools/binance-futures-coinm/market-api/indexPriceKlines.ts index e7f5d024..b8b4cf53 100644 --- a/src/tools/binance-futures-coinm/market-api/indexPriceKlines.ts +++ b/src/tools/binance-futures-coinm/market-api/indexPriceKlines.ts @@ -5,50 +5,71 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/indexPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryIndexPriceKlines(server: McpServer) { - server.tool( - "BinanceDeliveryIndexPriceKlines", - "Get index price kline/candlestick data for a COIN-M Futures pair.", - { - pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.indexPriceKlines({ - pair: params.pair, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📈 Index Price Klines for ${params.pair} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get index price klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryIndexPriceKlines", + { + description: "Get index price kline/candlestick data for a COIN-M Futures pair.", + inputSchema: { + pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.indexPriceKlines({ + pair: params.pair, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📈 Index Price Klines for ${params.pair} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get index price klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/klines.ts b/src/tools/binance-futures-coinm/market-api/klines.ts index 000201d6..2f499688 100644 --- a/src/tools/binance-futures-coinm/market-api/klines.ts +++ b/src/tools/binance-futures-coinm/market-api/klines.ts @@ -5,50 +5,71 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryKlines(server: McpServer) { - server.tool( - "BinanceDeliveryKlines", - "Get kline/candlestick data for a COIN-M Futures symbol.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.klines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `🕯️ Klines for ${params.symbol} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryKlines", + { + description: "Get kline/candlestick data for a COIN-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.klines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `🕯️ Klines for ${params.symbol} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/markPriceKlines.ts b/src/tools/binance-futures-coinm/market-api/markPriceKlines.ts index 84197832..e018f9f4 100644 --- a/src/tools/binance-futures-coinm/market-api/markPriceKlines.ts +++ b/src/tools/binance-futures-coinm/market-api/markPriceKlines.ts @@ -5,50 +5,72 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/markPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryMarkPriceKlines(server: McpServer) { - server.tool( - "BinanceDeliveryMarkPriceKlines", + server.registerTool( + "BinanceDeliveryMarkPriceKlines", + { + description: "Get mark price kline/candlestick data for a COIN-M Futures symbol. Mark price is used for liquidation calculations.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.markPriceKlines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Mark Price Klines for ${params.symbol} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get mark price klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of klines (default 500, max 1500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.markPriceKlines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Mark Price Klines for ${params.symbol} (${params.interval})\n\nCandles: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get mark price klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/openInterest.ts b/src/tools/binance-futures-coinm/market-api/openInterest.ts index 047515cb..6f795711 100644 --- a/src/tools/binance-futures-coinm/market-api/openInterest.ts +++ b/src/tools/binance-futures-coinm/market-api/openInterest.ts @@ -5,38 +5,45 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/openInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryOpenInterest(server: McpServer) { - server.tool( - "BinanceDeliveryOpenInterest", - "Get present open interest for a specific COIN-M Futures contract.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.openInterest({ - symbol: params.symbol - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Open Interest for ${params.symbol}\n\nOpen Interest: ${data.openInterest}\nSymbol: ${data.symbol}\nPair: ${data.pair}\nContract Type: ${data.contractType}\nTime: ${new Date(data.time).toISOString()}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get open interest: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryOpenInterest", + { + description: "Get present open interest for a specific COIN-M Futures contract.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.openInterest({ + symbol: params.symbol, + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Open Interest for ${params.symbol}\n\nOpen Interest: ${data.openInterest}\nSymbol: ${data.symbol}\nPair: ${data.pair}\nContract Type: ${data.contractType}\nTime: ${new Date(data.time).toISOString()}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get open interest: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/openInterestHist.ts b/src/tools/binance-futures-coinm/market-api/openInterestHist.ts index fc14c28c..ff7af6ef 100644 --- a/src/tools/binance-futures-coinm/market-api/openInterestHist.ts +++ b/src/tools/binance-futures-coinm/market-api/openInterestHist.ts @@ -5,48 +5,62 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/openInterestHist.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryOpenInterestHist(server: McpServer) { - server.tool( - "BinanceDeliveryOpenInterestHist", + server.registerTool( + "BinanceDeliveryOpenInterestHist", + { + description: "Get historical open interest for a COIN-M Futures pair. Requires VIP 2+ or higher.", - { - pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), - contractType: z.enum(["ALL", "PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]).describe("Contract type"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Time period"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 30, max 500)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.openInterestHist({ - pair: params.pair, - contractType: params.contractType, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📈 Historical Open Interest for ${params.pair} ${params.contractType}\n\nPeriod: ${params.period}\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get open interest history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + pair: z.string().describe("Underlying pair (e.g., BTCUSD)"), + contractType: z + .enum(["ALL", "PERPETUAL", "CURRENT_QUARTER", "NEXT_QUARTER"]) + .describe("Contract type"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Time period"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 30, max 500)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.openInterestHist({ + pair: params.pair, + contractType: params.contractType, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📈 Historical Open Interest for ${params.pair} ${params.contractType}\n\nPeriod: ${params.period}\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to get open interest history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/ping.ts b/src/tools/binance-futures-coinm/market-api/ping.ts index cc26e15a..90fde8a3 100644 --- a/src/tools/binance-futures-coinm/market-api/ping.ts +++ b/src/tools/binance-futures-coinm/market-api/ping.ts @@ -5,32 +5,38 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../../config/binanceClient.js"; export function registerBinanceDeliveryPing(server: McpServer) { - server.tool( - "BinanceDeliveryPing", + server.registerTool( + "BinanceDeliveryPing", + { + description: "Test connectivity to the COIN-M Futures API. Returns empty object if successful.", - {}, - async () => { - try { - const response = await deliveryClient.restAPI.ping(); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ COIN-M Futures API is reachable\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ COIN-M Futures API ping failed: ${errorMessage}` }], - isError: true - }; - } - } - ); + }, + async () => { + try { + const response = await deliveryClient.restAPI.ping(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ COIN-M Futures API is reachable\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ COIN-M Futures API ping failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/premiumIndex.ts b/src/tools/binance-futures-coinm/market-api/premiumIndex.ts index 8e328825..80b8fe76 100644 --- a/src/tools/binance-futures-coinm/market-api/premiumIndex.ts +++ b/src/tools/binance-futures-coinm/market-api/premiumIndex.ts @@ -5,38 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/premiumIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryPremiumIndex(server: McpServer) { - server.tool( - "BinanceDeliveryPremiumIndex", - "Get mark price and funding rate for COIN-M Futures contracts.", - { - symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.premiumIndex({ - ...(params.symbol && { symbol: params.symbol }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `💰 Premium Index${params.symbol ? ` for ${params.symbol}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get premium index: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryPremiumIndex", + { + description: "Get mark price and funding rate for COIN-M Futures contracts.", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.premiumIndex({ + ...(params.symbol && { symbol: params.symbol }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `💰 Premium Index${params.symbol ? ` for ${params.symbol}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get premium index: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/ticker24hr.ts b/src/tools/binance-futures-coinm/market-api/ticker24hr.ts index 2edb153f..40aea579 100644 --- a/src/tools/binance-futures-coinm/market-api/ticker24hr.ts +++ b/src/tools/binance-futures-coinm/market-api/ticker24hr.ts @@ -5,40 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDelivery24hrTicker(server: McpServer) { - server.tool( - "BinanceDelivery24hrTicker", - "Get 24hr rolling window price change statistics for COIN-M Futures.", - { - symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.ticker24hr({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 24hr Ticker${params.symbol ? ` for ${params.symbol}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get 24hr ticker: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDelivery24hrTicker", + { + description: "Get 24hr rolling window price change statistics for COIN-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), + pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.ticker24hr({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 24hr Ticker${params.symbol ? ` for ${params.symbol}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get 24hr ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/tickerPrice.ts b/src/tools/binance-futures-coinm/market-api/tickerPrice.ts index be696481..f28b61e8 100644 --- a/src/tools/binance-futures-coinm/market-api/tickerPrice.ts +++ b/src/tools/binance-futures-coinm/market-api/tickerPrice.ts @@ -5,40 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryTickerPrice(server: McpServer) { - server.tool( - "BinanceDeliveryTickerPrice", - "Get latest price for COIN-M Futures symbol(s).", - { - symbol: z.string().optional().describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.tickerPrice({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `💰 Symbol Price${params.symbol ? ` for ${params.symbol}` : ''}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get ticker price: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryTickerPrice", + { + description: "Get latest price for COIN-M Futures symbol(s).", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Contract symbol (e.g., BTCUSD_PERP). If not provided, returns all symbols"), + pair: z.string().optional().describe("Filter by underlying pair (e.g., BTCUSD)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.tickerPrice({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `💰 Symbol Price${params.symbol ? ` for ${params.symbol}` : ""}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get ticker price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/time.ts b/src/tools/binance-futures-coinm/market-api/time.ts index a6a93a31..f3d9247b 100644 --- a/src/tools/binance-futures-coinm/market-api/time.ts +++ b/src/tools/binance-futures-coinm/market-api/time.ts @@ -5,32 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../../config/binanceClient.js"; export function registerBinanceDeliveryTime(server: McpServer) { - server.tool( - "BinanceDeliveryTime", - "Get the current server time from COIN-M Futures API.", - {}, - async () => { - try { - const response = await deliveryClient.restAPI.time(); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `🕐 COIN-M Futures Server Time\n\nTimestamp: ${data.serverTime}\nDate: ${new Date(data.serverTime).toISOString()}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get server time: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryTime", + { description: "Get the current server time from COIN-M Futures API." }, + async () => { + try { + const response = await deliveryClient.restAPI.time(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `🕐 COIN-M Futures Server Time\n\nTimestamp: ${data.serverTime}\nDate: ${new Date(data.serverTime).toISOString()}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/market-api/trades.ts b/src/tools/binance-futures-coinm/market-api/trades.ts index 1c539134..b1d7e611 100644 --- a/src/tools/binance-futures-coinm/market-api/trades.ts +++ b/src/tools/binance-futures-coinm/market-api/trades.ts @@ -5,40 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/market-api/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryTrades(server: McpServer) { - server.tool( - "BinanceDeliveryTrades", - "Get recent trades for a COIN-M Futures symbol.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.trades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📈 Recent Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryTrades", + { + description: "Get recent trades for a COIN-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + limit: z.number().int().optional().describe("Number of trades (default 500, max 1000)"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.trades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📈 Recent Trades for ${params.symbol}\n\nTrades: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/newOrder.ts b/src/tools/binance-futures-coinm/newOrder.ts index f856c65c..00deb303 100644 --- a/src/tools/binance-futures-coinm/newOrder.ts +++ b/src/tools/binance-futures-coinm/newOrder.ts @@ -1,51 +1,69 @@ // src/tools/binance-futures-coinm/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMNewOrder(server: McpServer) { - server.tool( - "BinanceFuturesCOINMNewOrder", - "Send a new COIN-M futures order.", - { - symbol: z.string().describe("Trading symbol (e.g., BTCUSD_PERP)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"]).describe("Order type"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for hedge mode"), - quantity: z.number().optional().describe("Order quantity"), - price: z.number().optional().describe("Order price (required for LIMIT orders)"), - stopPrice: z.number().optional().describe("Stop price for stop orders"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), - reduceOnly: z.boolean().optional().describe("Reduce only order"), - newClientOrderId: z.string().optional().describe("Client order ID"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.newOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M order placed: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place COIN-M order: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMNewOrder", + { + description: "Send a new COIN-M futures order.", + inputSchema: { + symbol: z.string().describe("Trading symbol (e.g., BTCUSD_PERP)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for hedge mode"), + quantity: z.number().optional().describe("Order quantity"), + price: z.number().optional().describe("Order price (required for LIMIT orders)"), + stopPrice: z.number().optional().describe("Stop price for stop orders"), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), + reduceOnly: z.boolean().optional().describe("Reduce only order"), + newClientOrderId: z.string().optional().describe("Client order ID"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.newOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M order placed: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to place COIN-M order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/openInterest.ts b/src/tools/binance-futures-coinm/openInterest.ts index a201e6a5..50276523 100644 --- a/src/tools/binance-futures-coinm/openInterest.ts +++ b/src/tools/binance-futures-coinm/openInterest.ts @@ -1,37 +1,44 @@ // src/tools/binance-futures-coinm/openInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMOpenInterest(server: McpServer) { - server.tool( - "BinanceFuturesCOINMOpenInterest", - "Get present open interest of a specific symbol for COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)") - }, - async ({ symbol }) => { - try { - const data = await deliveryClient.openInterest({ symbol }); - + server.registerTool( + "BinanceFuturesCOINMOpenInterest", + { + description: "Get present open interest of a specific symbol for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + }, + }, + async ({ symbol }) => { + try { + const data = await deliveryClient.openInterest({ symbol }); + + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures open interest for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures open interest for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures open interest: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures open interest: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/openOrders.ts b/src/tools/binance-futures-coinm/openOrders.ts index b6dc3e8b..e98c1129 100644 --- a/src/tools/binance-futures-coinm/openOrders.ts +++ b/src/tools/binance-futures-coinm/openOrders.ts @@ -1,35 +1,40 @@ // src/tools/binance-futures-coinm/openOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMOpenOrders(server: McpServer) { - server.tool( - "BinanceFuturesCOINMOpenOrders", - "Get current COIN-M futures open orders.", - { - symbol: z.string().optional().describe("Trading symbol (optional)"), - pair: z.string().optional().describe("Trading pair"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.openOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M open orders: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get COIN-M open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMOpenOrders", + { + description: "Get current COIN-M futures open orders.", + inputSchema: { + symbol: z.string().optional().describe("Trading symbol (optional)"), + pair: z.string().optional().describe("Trading pair"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.openOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M open orders: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get COIN-M open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/ping.ts b/src/tools/binance-futures-coinm/ping.ts index a40095ec..92d1efab 100644 --- a/src/tools/binance-futures-coinm/ping.ts +++ b/src/tools/binance-futures-coinm/ping.ts @@ -1,33 +1,32 @@ // src/tools/binance-futures-coinm/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMPing(server: McpServer) { - server.tool( - "BinanceFuturesCOINMPing", - "Test connectivity to the COIN-M Futures REST API.", - {}, - async () => { - try { - const data = await deliveryClient.ping(); - - return { - content: [ - { - type: "text", - text: `COIN-M Futures API connectivity test successful. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to ping COIN-M Futures API: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMPing", + { description: "Test connectivity to the COIN-M Futures REST API." }, + async () => { + try { + const data = await deliveryClient.ping(); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures API connectivity test successful. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to ping COIN-M Futures API: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/positionMargin.ts b/src/tools/binance-futures-coinm/positionMargin.ts index 51706e64..bf80e5af 100644 --- a/src/tools/binance-futures-coinm/positionMargin.ts +++ b/src/tools/binance-futures-coinm/positionMargin.ts @@ -1,44 +1,53 @@ // src/tools/binance-futures-coinm/positionMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMPositionMargin(server: McpServer) { - server.tool( - "BinanceFuturesCOINMPositionMargin", - "Modify isolated position margin for COIN-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side. Default BOTH for One-way Mode"), - amount: z.number().describe("Amount to add or remove"), - type: z.number().describe("1: Add margin, 2: Remove margin") - }, - async ({ symbol, positionSide, amount, type }) => { - try { - const params: any = { symbol, amount, type }; - if (positionSide) params.positionSide = positionSide; + server.registerTool( + "BinanceFuturesCOINMPositionMargin", + { + description: "Modify isolated position margin for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side. Default BOTH for One-way Mode"), + amount: z.number().describe("Amount to add or remove"), + type: z.number().describe("1: Add margin, 2: Remove margin"), + }, + }, + async ({ symbol, positionSide, amount, type }) => { + try { + const params: any = { symbol, amount, type }; + if (positionSide) params.positionSide = positionSide; - const data = await deliveryClient.positionMargin(params); - + const data = await deliveryClient.positionMargin(params); - return { - content: [ - { - type: "text", - text: `COIN-M Futures position margin modified for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to modify COIN-M Futures position margin: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} + return { + content: [ + { + type: "text", + text: `COIN-M Futures position margin modified for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: [ + { + type: "text", + text: `Failed to modify COIN-M Futures position margin: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-futures-coinm/positionMode.ts b/src/tools/binance-futures-coinm/positionMode.ts index 06da8f34..73a64457 100644 --- a/src/tools/binance-futures-coinm/positionMode.ts +++ b/src/tools/binance-futures-coinm/positionMode.ts @@ -1,37 +1,46 @@ // src/tools/binance-futures-coinm/positionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMPositionMode(server: McpServer) { - server.tool( - "BinanceFuturesCOINMPositionMode", - "Change position mode for COIN-M Futures (One-way or Hedge Mode).", - { - dualSidePosition: z.boolean().describe("true: Hedge Mode, false: One-way Mode") - }, - async ({ dualSidePosition }) => { - try { - const data = await deliveryClient.positionSideDual({ dualSidePosition: dualSidePosition ? "true" : "false" }); - + server.registerTool( + "BinanceFuturesCOINMPositionMode", + { + description: "Change position mode for COIN-M Futures (One-way or Hedge Mode).", + inputSchema: { + dualSidePosition: z.boolean().describe("true: Hedge Mode, false: One-way Mode"), + }, + }, + async ({ dualSidePosition }) => { + try { + const data = await deliveryClient.positionMode({ + dualSidePosition: dualSidePosition ? "true" : "false", + }); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures position mode changed to ${dualSidePosition ? "Hedge Mode" : "One-way Mode"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `COIN-M Futures position mode changed to ${dualSidePosition ? 'Hedge Mode' : 'One-way Mode'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change COIN-M Futures position mode: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to change COIN-M Futures position mode: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/positionRisk.ts b/src/tools/binance-futures-coinm/positionRisk.ts index e035ad17..629c27e0 100644 --- a/src/tools/binance-futures-coinm/positionRisk.ts +++ b/src/tools/binance-futures-coinm/positionRisk.ts @@ -1,35 +1,40 @@ // src/tools/binance-futures-coinm/positionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../config/binanceClient.js"; + export function registerBinanceFuturesCOINMPositionRisk(server: McpServer) { - server.tool( - "BinanceFuturesCOINMPositionRisk", - "Get COIN-M futures position information.", - { - marginAsset: z.string().optional().describe("Margin asset"), - pair: z.string().optional().describe("Trading pair"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await deliveryClient.getPositionRisk({ - ...(params.marginAsset && { marginAsset: params.marginAsset }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - return { - content: [{ type: "text", text: `COIN-M position risk: ${JSON.stringify(data)}` }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get COIN-M position risk: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMPositionRisk", + { + description: "Get COIN-M futures position information.", + inputSchema: { + marginAsset: z.string().optional().describe("Margin asset"), + pair: z.string().optional().describe("Trading pair"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await deliveryClient.positionRisk({ + ...(params.marginAsset && { marginAsset: params.marginAsset }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [{ type: "text", text: `COIN-M position risk: ${JSON.stringify(data)}` }], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get COIN-M position risk: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/premiumIndex.ts b/src/tools/binance-futures-coinm/premiumIndex.ts index 382bf906..04d3d339 100644 --- a/src/tools/binance-futures-coinm/premiumIndex.ts +++ b/src/tools/binance-futures-coinm/premiumIndex.ts @@ -1,40 +1,52 @@ // src/tools/binance-futures-coinm/premiumIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMPremiumIndex(server: McpServer) { - server.tool( - "BinanceFuturesCOINMPremiumIndex", - "Get mark price and funding rate for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesCOINMPremiumIndex", + { + description: "Get mark price and funding rate for COIN-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await deliveryClient.premiumIndex(params); - const data = await deliveryClient.premiumIndex(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures premium index${symbol ? ` for ${symbol}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures premium index${symbol ? ` for ${symbol}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures premium index: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures premium index: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/ticker24hr.ts b/src/tools/binance-futures-coinm/ticker24hr.ts index f813d372..1bc55f50 100644 --- a/src/tools/binance-futures-coinm/ticker24hr.ts +++ b/src/tools/binance-futures-coinm/ticker24hr.ts @@ -1,42 +1,54 @@ // src/tools/binance-futures-coinm/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMTicker24hr(server: McpServer) { - server.tool( - "BinanceFuturesCOINMTicker24hr", - "Get 24-hour rolling window price change statistics for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)") - }, - async ({ symbol, pair }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (pair) params.pair = pair; + server.registerTool( + "BinanceFuturesCOINMTicker24hr", + { + description: "Get 24-hour rolling window price change statistics for COIN-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols", + ), + pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + }, + }, + async ({ symbol, pair }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (pair) params.pair = pair; + + const data = await deliveryClient.ticker24hr(params); - const data = await deliveryClient.ticker24hr(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures 24hr ticker${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures 24hr ticker${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures 24hr ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures 24hr ticker: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/tickerPrice.ts b/src/tools/binance-futures-coinm/tickerPrice.ts index 2197ea1a..8c8d14a8 100644 --- a/src/tools/binance-futures-coinm/tickerPrice.ts +++ b/src/tools/binance-futures-coinm/tickerPrice.ts @@ -1,42 +1,54 @@ // src/tools/binance-futures-coinm/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMTickerPrice(server: McpServer) { - server.tool( - "BinanceFuturesCOINMTickerPrice", - "Get latest price for a symbol or symbols for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols"), - pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)") - }, - async ({ symbol, pair }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (pair) params.pair = pair; + server.registerTool( + "BinanceFuturesCOINMTickerPrice", + { + description: "Get latest price for a symbol or symbols for COIN-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSD_PERP). If not provided, returns all symbols", + ), + pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + }, + }, + async ({ symbol, pair }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (pair) params.pair = pair; + + const data = await deliveryClient.tickerPrice(params); - const data = await deliveryClient.tickerPrice(params); - + return { + content: [ + { + type: "text", + text: `Retrieved COIN-M Futures ticker price${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved COIN-M Futures ticker price${symbol ? ` for ${symbol}` : pair ? ` for pair ${pair}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures ticker price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures ticker price: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/time.ts b/src/tools/binance-futures-coinm/time.ts index 64627f51..000f1bbe 100644 --- a/src/tools/binance-futures-coinm/time.ts +++ b/src/tools/binance-futures-coinm/time.ts @@ -1,33 +1,34 @@ // src/tools/binance-futures-coinm/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMTime(server: McpServer) { - server.tool( - "BinanceFuturesCOINMTime", - "Get the current server time from the COIN-M Futures API.", - {}, - async () => { - try { - const data = await deliveryClient.time(); - - return { - content: [ - { - type: "text", - text: `COIN-M Futures server time: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get COIN-M Futures server time: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCOINMTime", + { description: "Get the current server time from the COIN-M Futures API." }, + async () => { + try { + const data = await deliveryClient.time(); + + return { + content: [ + { + type: "text", + text: `COIN-M Futures server time: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get COIN-M Futures server time: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/allOrders.ts b/src/tools/binance-futures-coinm/trade-api/allOrders.ts index 42c7f12a..89b95535 100644 --- a/src/tools/binance-futures-coinm/trade-api/allOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/allOrders.ts @@ -5,50 +5,57 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryAllOrders(server: McpServer) { - server.tool( - "BinanceDeliveryAllOrders", - "Get all COIN-M Futures account orders (active, canceled, or filled).", - { - symbol: z.string().optional().describe("Contract symbol filter"), - pair: z.string().optional().describe("Filter by underlying pair"), - orderId: z.number().int().optional().describe("Return orders >= this orderId"), - startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().int().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.allOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📋 All Orders\n\nCount: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryAllOrders", + { + description: "Get all COIN-M Futures account orders (active, canceled, or filled).", + inputSchema: { + symbol: z.string().optional().describe("Contract symbol filter"), + pair: z.string().optional().describe("Filter by underlying pair"), + orderId: z.number().int().optional().describe("Return orders >= this orderId"), + startTime: z.number().int().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().int().optional().describe("End timestamp in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.allOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📋 All Orders\n\nCount: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/batchOrders.ts b/src/tools/binance-futures-coinm/trade-api/batchOrders.ts index 35ee426e..9e2fe02d 100644 --- a/src/tools/binance-futures-coinm/trade-api/batchOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/batchOrders.ts @@ -5,44 +5,53 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryBatchOrders(server: McpServer) { - server.tool( - "BinanceDeliveryBatchOrders", - "Place multiple COIN-M Futures orders in batch (max 5 orders).", - { - batchOrders: z.string().describe("JSON string array of orders. Each order must have: symbol, side, type") - }, - async (params) => { - try { - const orders = JSON.parse(params.batchOrders); - - if (!Array.isArray(orders) || orders.length === 0 || orders.length > 5) { - return { - content: [{ type: "text", text: "Error: batchOrders must be an array of 1-5 orders" }], - isError: true - }; - } + server.registerTool( + "BinanceDeliveryBatchOrders", + { + description: "Place multiple COIN-M Futures orders in batch (max 5 orders).", + inputSchema: { + batchOrders: z + .string() + .describe("JSON string array of orders. Each order must have: symbol, side, type"), + }, + }, + async (params) => { + try { + const orders = JSON.parse(params.batchOrders); - const response = await deliveryClient.restAPI.placeMultipleOrders({ batchOrders: orders }); - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Batch orders placed!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to place batch orders: ${errorMessage}` }], - isError: true - }; - } + if (!Array.isArray(orders) || orders.length === 0 || orders.length > 5) { + return { + content: [{ type: "text", text: "Error: batchOrders must be an array of 1-5 orders" }], + isError: true, + }; } - ); + + const response = await deliveryClient.restAPI.placeMultipleOrders({ batchOrders: orders }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Batch orders placed!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to place batch orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/cancelAllOrders.ts b/src/tools/binance-futures-coinm/trade-api/cancelAllOrders.ts index 1f11d3e9..51ba6fc0 100644 --- a/src/tools/binance-futures-coinm/trade-api/cancelAllOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/cancelAllOrders.ts @@ -5,40 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCancelAllOrders(server: McpServer) { - server.tool( - "BinanceDeliveryCancelAllOrders", - "Cancel all open COIN-M Futures orders for a symbol. ⚠️ Use with caution!", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.cancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All orders cancelled for ${params.symbol}!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryCancelAllOrders", + { + description: "Cancel all open COIN-M Futures orders for a symbol. ⚠️ Use with caution!", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.cancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ All orders cancelled for ${params.symbol}!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/cancelBatchOrders.ts b/src/tools/binance-futures-coinm/trade-api/cancelBatchOrders.ts index b8640bcf..0503cec3 100644 --- a/src/tools/binance-futures-coinm/trade-api/cancelBatchOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/cancelBatchOrders.ts @@ -5,51 +5,65 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceDeliveryCancelBatchOrders", - "Cancel multiple COIN-M Futures orders in batch (max 10).", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - orderIdList: z.string().optional().describe("JSON array of order IDs to cancel"), - origClientOrderIdList: z.string().optional().describe("JSON array of client order IDs"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderIdList && !params.origClientOrderIdList) { - return { - content: [{ type: "text", text: "Error: Either orderIdList or origClientOrderIdList must be provided" }], - isError: true - }; - } - - const response = await deliveryClient.restAPI.cancelMultipleOrders({ - symbol: params.symbol, - ...(params.orderIdList && { orderIdList: JSON.parse(params.orderIdList) }), - ...(params.origClientOrderIdList && { origClientOrderIdList: JSON.parse(params.origClientOrderIdList) }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Batch orders cancelled!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel batch orders: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceDeliveryCancelBatchOrders", + { + description: "Cancel multiple COIN-M Futures orders in batch (max 10).", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + orderIdList: z.string().optional().describe("JSON array of order IDs to cancel"), + origClientOrderIdList: z.string().optional().describe("JSON array of client order IDs"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderIdList && !params.origClientOrderIdList) { + return { + content: [ + { + type: "text", + text: "Error: Either orderIdList or origClientOrderIdList must be provided", + }, + ], + isError: true, + }; } - ); + + const response = await deliveryClient.restAPI.cancelMultipleOrders({ + symbol: params.symbol, + ...(params.orderIdList && { orderIdList: JSON.parse(params.orderIdList) }), + ...(params.origClientOrderIdList && { + origClientOrderIdList: JSON.parse(params.origClientOrderIdList), + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Batch orders cancelled!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel batch orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/cancelOrder.ts b/src/tools/binance-futures-coinm/trade-api/cancelOrder.ts index 5521e3b9..9db198eb 100644 --- a/src/tools/binance-futures-coinm/trade-api/cancelOrder.ts +++ b/src/tools/binance-futures-coinm/trade-api/cancelOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCancelOrder(server: McpServer) { - server.tool( - "BinanceDeliveryCancelOrder", - "Cancel an active COIN-M Futures order.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await deliveryClient.restAPI.cancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Order cancelled!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceDeliveryCancelOrder", + { + description: "Cancel an active COIN-M Futures order.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await deliveryClient.restAPI.cancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Order cancelled!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/changeLeverage.ts b/src/tools/binance-futures-coinm/trade-api/changeLeverage.ts index 5c9a3a6a..be989504 100644 --- a/src/tools/binance-futures-coinm/trade-api/changeLeverage.ts +++ b/src/tools/binance-futures-coinm/trade-api/changeLeverage.ts @@ -5,42 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/changeLeverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryChangeLeverage(server: McpServer) { - server.tool( - "BinanceDeliveryChangeLeverage", + server.registerTool( + "BinanceDeliveryChangeLeverage", + { + description: "Change initial leverage for a COIN-M Futures symbol. ⚠️ Higher leverage = higher risk.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.changeInitialLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Leverage changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional: ${data.maxQty}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change leverage: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.changeInitialLeverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Leverage changed!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional: ${data.maxQty}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change leverage: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/changeMarginType.ts b/src/tools/binance-futures-coinm/trade-api/changeMarginType.ts index f20025fa..3ccbba8a 100644 --- a/src/tools/binance-futures-coinm/trade-api/changeMarginType.ts +++ b/src/tools/binance-futures-coinm/trade-api/changeMarginType.ts @@ -5,42 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/changeMarginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryChangeMarginType(server: McpServer) { - server.tool( - "BinanceDeliveryChangeMarginType", - "Change margin type between ISOLATED and CROSSED for COIN-M Futures.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.changeMarginType({ - symbol: params.symbol, - marginType: params.marginType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Margin type changed to ${params.marginType}!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change margin type: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryChangeMarginType", + { + description: "Change margin type between ISOLATED and CROSSED for COIN-M Futures.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.changeMarginType({ + symbol: params.symbol, + marginType: params.marginType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Margin type changed to ${params.marginType}!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change margin type: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/changePositionMode.ts b/src/tools/binance-futures-coinm/trade-api/changePositionMode.ts index 601eb3ca..0ca57811 100644 --- a/src/tools/binance-futures-coinm/trade-api/changePositionMode.ts +++ b/src/tools/binance-futures-coinm/trade-api/changePositionMode.ts @@ -5,41 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/changePositionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryChangePositionMode(server: McpServer) { - server.tool( - "BinanceDeliveryChangePositionMode", - "Change COIN-M Futures position mode between Hedge Mode and One-way Mode.", - { - dualSidePosition: z.boolean().describe("true = Hedge Mode, false = One-way Mode"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.changePositionMode({ - dualSidePosition: params.dualSidePosition, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const mode = params.dualSidePosition ? "Hedge Mode" : "One-way Mode"; - - return { - content: [{ - type: "text", - text: `✅ Position mode changed to ${mode}!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change position mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryChangePositionMode", + { + description: "Change COIN-M Futures position mode between Hedge Mode and One-way Mode.", + inputSchema: { + dualSidePosition: z.boolean().describe("true = Hedge Mode, false = One-way Mode"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.changePositionMode({ + dualSidePosition: params.dualSidePosition, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const mode = params.dualSidePosition ? "Hedge Mode" : "One-way Mode"; + + return { + content: [ + { + type: "text", + text: `✅ Position mode changed to ${mode}!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change position mode: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/countdownCancelAll.ts b/src/tools/binance-futures-coinm/trade-api/countdownCancelAll.ts index 83ba5f4b..1f964e03 100644 --- a/src/tools/binance-futures-coinm/trade-api/countdownCancelAll.ts +++ b/src/tools/binance-futures-coinm/trade-api/countdownCancelAll.ts @@ -5,44 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/countdownCancelAll.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCountdownCancelAll(server: McpServer) { - server.tool( - "BinanceDeliveryCountdownCancelAll", + server.registerTool( + "BinanceDeliveryCountdownCancelAll", + { + description: "Set countdown timer to cancel all COIN-M orders. Dead man's switch. Set to 0 to cancel.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - countdownTime: z.number().int().describe("Countdown in milliseconds. 0 to cancel. Min 10000"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.autoCancelAllOpenOrders({ - symbol: params.symbol, - countdownTime: params.countdownTime, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: params.countdownTime === 0 - ? `✅ Countdown cancelled!\n\n${JSON.stringify(data, null, 2)}` - : `⏱️ Countdown set! Orders will cancel in ${params.countdownTime / 1000}s\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to set countdown: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + countdownTime: z + .number() + .int() + .describe("Countdown in milliseconds. 0 to cancel. Min 10000"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.autoCancelAllOpenOrders({ + symbol: params.symbol, + countdownTime: params.countdownTime, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: + params.countdownTime === 0 + ? `✅ Countdown cancelled!\n\n${JSON.stringify(data, null, 2)}` + : `⏱️ Countdown set! Orders will cancel in ${params.countdownTime / 1000}s\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to set countdown: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/getAllOrders.ts b/src/tools/binance-futures-coinm/trade-api/getAllOrders.ts index bbce5cc3..5c5efb2b 100644 --- a/src/tools/binance-futures-coinm/trade-api/getAllOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/getAllOrders.ts @@ -5,55 +5,66 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/getAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryGetAllOrders(server: McpServer) { - server.tool( - "BinanceDeliveryGetAllOrders", - "Get all COIN-M Futures orders (active, canceled, filled) for a symbol.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - pair: z.string().optional().describe("Contract pair (e.g., BTCUSD)"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of orders (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.allOrders({ - symbol: params.symbol, - ...(params.pair && { pair: params.pair }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceDeliveryGetAllOrders", + { + description: "Get all COIN-M Futures orders (active, canceled, filled) for a symbol.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + pair: z.string().optional().describe("Contract pair (e.g., BTCUSD)"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of orders (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.allOrders({ + symbol: params.symbol, + ...(params.pair && { pair: params.pair }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const orders = Array.isArray(data) ? data : [data]; - const data = await response.data(); - const orders = Array.isArray(data) ? data : [data]; + const summary = orders + .slice(0, 10) + .map( + (o: any) => + `${o.symbol}: ${o.side} ${o.type} ${o.origQty} @ ${o.price || "MARKET"} - ${o.status}`, + ) + .join("\n"); - const summary = orders.slice(0, 10).map((o: any) => - `${o.symbol}: ${o.side} ${o.type} ${o.origQty} @ ${o.price || 'MARKET'} - ${o.status}` - ).join('\n'); + return { + content: [ + { + type: "text", + text: `📋 All Orders for ${params.symbol} (${orders.length} total)\n\n${summary}\n\nFull data: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `📋 All Orders for ${params.symbol} (${orders.length} total)\n\n${summary}\n\nFull data: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/getOrder.ts b/src/tools/binance-futures-coinm/trade-api/getOrder.ts index c394d70c..65b53e60 100644 --- a/src/tools/binance-futures-coinm/trade-api/getOrder.ts +++ b/src/tools/binance-futures-coinm/trade-api/getOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryGetOrder(server: McpServer) { - server.tool( - "BinanceDeliveryGetOrder", - "Query a specific COIN-M Futures order's status.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await deliveryClient.restAPI.queryOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📋 Order Details\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nStatus: ${data.status}\nSide: ${data.side}\nType: ${data.type}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceDeliveryGetOrder", + { + description: "Query a specific COIN-M Futures order's status.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await deliveryClient.restAPI.queryOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📋 Order Details\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nStatus: ${data.status}\nSide: ${data.side}\nType: ${data.type}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/index.ts b/src/tools/binance-futures-coinm/trade-api/index.ts index 8f635876..64d4ac47 100644 --- a/src/tools/binance-futures-coinm/trade-api/index.ts +++ b/src/tools/binance-futures-coinm/trade-api/index.ts @@ -5,44 +5,45 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDeliveryNewOrder } from "./newOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceDeliveryAllOrders } from "./allOrders.js"; import { registerBinanceDeliveryBatchOrders } from "./batchOrders.js"; -import { registerBinanceDeliveryGetOrder } from "./getOrder.js"; -import { registerBinanceDeliveryCancelOrder } from "./cancelOrder.js"; import { registerBinanceDeliveryCancelAllOrders } from "./cancelAllOrders.js"; import { registerBinanceDeliveryCancelBatchOrders } from "./cancelBatchOrders.js"; -import { registerBinanceDeliveryCountdownCancelAll } from "./countdownCancelAll.js"; -import { registerBinanceDeliveryOpenOrder } from "./openOrder.js"; -import { registerBinanceDeliveryOpenOrders } from "./openOrders.js"; -import { registerBinanceDeliveryAllOrders } from "./allOrders.js"; +import { registerBinanceDeliveryCancelOrder } from "./cancelOrder.js"; import { registerBinanceDeliveryChangeLeverage } from "./changeLeverage.js"; import { registerBinanceDeliveryChangeMarginType } from "./changeMarginType.js"; -import { registerBinanceDeliveryModifyIsolatedPositionMargin } from "./modifyIsolatedPositionMargin.js"; import { registerBinanceDeliveryChangePositionMode } from "./changePositionMode.js"; +import { registerBinanceDeliveryCountdownCancelAll } from "./countdownCancelAll.js"; +import { registerBinanceDeliveryGetOrder } from "./getOrder.js"; +import { registerBinanceDeliveryModifyIsolatedPositionMargin } from "./modifyIsolatedPositionMargin.js"; +import { registerBinanceDeliveryNewOrder } from "./newOrder.js"; +import { registerBinanceDeliveryOpenOrder } from "./openOrder.js"; +import { registerBinanceDeliveryOpenOrders } from "./openOrders.js"; export function registerBinanceDeliveryTradeApiTools(server: McpServer) { - // Order Placement - registerBinanceDeliveryNewOrder(server); - registerBinanceDeliveryBatchOrders(server); - - // Order Query - registerBinanceDeliveryGetOrder(server); - registerBinanceDeliveryOpenOrder(server); - registerBinanceDeliveryOpenOrders(server); - registerBinanceDeliveryAllOrders(server); - - // Order Cancellation - registerBinanceDeliveryCancelOrder(server); - registerBinanceDeliveryCancelAllOrders(server); - registerBinanceDeliveryCancelBatchOrders(server); - registerBinanceDeliveryCountdownCancelAll(server); - - // Leverage & Margin - registerBinanceDeliveryChangeLeverage(server); - registerBinanceDeliveryChangeMarginType(server); - registerBinanceDeliveryModifyIsolatedPositionMargin(server); - - // Position Mode - registerBinanceDeliveryChangePositionMode(server); + // Order Placement + registerBinanceDeliveryNewOrder(server); + registerBinanceDeliveryBatchOrders(server); + + // Order Query + registerBinanceDeliveryGetOrder(server); + registerBinanceDeliveryOpenOrder(server); + registerBinanceDeliveryOpenOrders(server); + registerBinanceDeliveryAllOrders(server); + + // Order Cancellation + registerBinanceDeliveryCancelOrder(server); + registerBinanceDeliveryCancelAllOrders(server); + registerBinanceDeliveryCancelBatchOrders(server); + registerBinanceDeliveryCountdownCancelAll(server); + + // Leverage & Margin + registerBinanceDeliveryChangeLeverage(server); + registerBinanceDeliveryChangeMarginType(server); + registerBinanceDeliveryModifyIsolatedPositionMargin(server); + + // Position Mode + registerBinanceDeliveryChangePositionMode(server); } diff --git a/src/tools/binance-futures-coinm/trade-api/modifyIsolatedPositionMargin.ts b/src/tools/binance-futures-coinm/trade-api/modifyIsolatedPositionMargin.ts index e94d37bf..888baf6e 100644 --- a/src/tools/binance-futures-coinm/trade-api/modifyIsolatedPositionMargin.ts +++ b/src/tools/binance-futures-coinm/trade-api/modifyIsolatedPositionMargin.ts @@ -5,47 +5,57 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/modifyIsolatedPositionMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryModifyIsolatedPositionMargin(server: McpServer) { - server.tool( - "BinanceDeliveryModifyIsolatedPositionMargin", - "Add or reduce margin to/from an isolated COIN-M Futures position.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - amount: z.string().describe("Amount of margin to add or reduce"), - type: z.enum(["1", "2"]).describe("1 = Add margin, 2 = Reduce margin"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.modifyIsolatedPositionMargin({ - symbol: params.symbol, - amount: params.amount, - type: parseInt(params.type) as 1 | 2, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const action = params.type === "1" ? "added to" : "reduced from"; - - return { - content: [{ - type: "text", - text: `✅ Margin ${action} position!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to modify position margin: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryModifyIsolatedPositionMargin", + { + description: "Add or reduce margin to/from an isolated COIN-M Futures position.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + amount: z.string().describe("Amount of margin to add or reduce"), + type: z.enum(["1", "2"]).describe("1 = Add margin, 2 = Reduce margin"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for Hedge Mode"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.modifyIsolatedPositionMargin({ + symbol: params.symbol, + amount: params.amount, + type: parseInt(params.type) as 1 | 2, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const action = params.type === "1" ? "added to" : "reduced from"; + + return { + content: [ + { + type: "text", + text: `✅ Margin ${action} position!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to modify position margin: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/newOrder.ts b/src/tools/binance-futures-coinm/trade-api/newOrder.ts index 4a174655..8f5c618b 100644 --- a/src/tools/binance-futures-coinm/trade-api/newOrder.ts +++ b/src/tools/binance-futures-coinm/trade-api/newOrder.ts @@ -1,151 +1,102 @@ -/** - * @author nich - * @website x.com/nichxbt - * @github github.com/nirholas - * @license Apache-2.0 - */ -// src/tools/binance-futures-coinm/trade-api/newOrder.ts// src/tools/binance-futures-coinm/trade-api/newOrder.ts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { z } from "zod"; -} ); } } }; isError: true content: [{ type: "text", text: `❌ Failed to place order: ${errorMessage}` }], return { const errorMessage = error instanceof Error ? error.message : String(error); } catch (error) { }; }] text: `✅ COIN-M order placed successfully!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` type: "text", content: [{ return { const data = await response.data(); }); ...(params.recvWindow && { recvWindow: params.recvWindow }) ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), ...(params.priceProtect !== undefined && { priceProtect: params.priceProtect }), ...(params.workingType && { workingType: params.workingType }), ...(params.callbackRate && { callbackRate: params.callbackRate }), ...(params.activationPrice && { activationPrice: params.activationPrice }), ...(params.closePosition !== undefined && { closePosition: params.closePosition }), ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), ...(params.timeInForce && { timeInForce: params.timeInForce }), ...(params.stopPrice && { stopPrice: params.stopPrice }), ...(params.price && { price: params.price }), ...(params.quantity && { quantity: params.quantity }), ...(params.positionSide && { positionSide: params.positionSide }), type: params.type, side: params.side, symbol: params.symbol, const response = await deliveryClient.restAPI.newOrder({ try { async (params) => { }, recvWindow: z.number().int().optional().describe("Recv window in milliseconds") newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), newClientOrderId: z.string().optional().describe("Custom order ID"), priceProtect: z.boolean().optional().describe("Price protection"), workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional().describe("Stop trigger type"), callbackRate: z.string().optional().describe("Callback rate for TRAILING_STOP_MARKET"), activationPrice: z.string().optional().describe("Activation price for TRAILING_STOP_MARKET"), closePosition: z.boolean().optional().describe("Close entire position"), reduceOnly: z.boolean().optional().describe("Reduce position only"), timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), stopPrice: z.string().optional().describe("Stop price for STOP/TAKE_PROFIT orders"), price: z.string().optional().describe("Limit price (required for LIMIT orders)"), quantity: z.string().optional().describe("Order quantity in contracts"), ]).describe("Order type"), "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET" "LIMIT", "MARKET", "STOP", "STOP_MARKET", type: z.enum([ positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode"), side: z.enum(["BUY", "SELL"]).describe("Order side"), symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), { "Place a new COIN-M Futures order. ⚠️ RISK: Futures trading involves leverage and liquidation risk.", "BinanceDeliveryNewOrder", server.tool(export function registerBinanceDeliveryNewOrder(server: McpServer) {import { z } from "zod";import { deliveryClient } from "../../../config/binanceClient.js";import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { deliveryClient } from "../../../config/binanceClient.js"; -import { z } from "zod"; export function registerBinanceDeliveryNewOrder(server: McpServer) { - server.tool( - "BinanceDeliveryNewOrder", + server.registerTool( + "BinanceDeliveryNewOrder", + { + description: "Place a new COIN-M Futures (Delivery) order. COIN-M futures are settled in the coin itself (e.g., BTC). ⚠️ RISK: Futures trading involves leverage and liquidation risk.", - { - symbol: z.string().describe("Delivery futures symbol (e.g., BTCUSD_PERP, BTCUSD_240329)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode. Use BOTH for One-Way Mode"), - type: z.enum([ - "LIMIT", "MARKET", "STOP", "STOP_MARKET", - "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET" - ]).describe("Order type"), - quantity: z.string().optional().describe("Order quantity in contracts"), - price: z.string().optional().describe("Limit price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), - reduceOnly: z.boolean().optional().describe("Reduce position only"), - closePosition: z.boolean().optional().describe("Close entire position"), - activationPrice: z.string().optional().describe("Activation price for TRAILING_STOP_MARKET"), - callbackRate: z.string().optional().describe("Callback rate for TRAILING_STOP_MARKET (0.1% - 5%)"), - workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional().describe("Stop price trigger type"), - priceProtect: z.boolean().optional().describe("Price protection"), - newClientOrderId: z.string().optional().describe("Custom order ID"), - newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.newOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.closePosition !== undefined && { closePosition: params.closePosition }), - ...(params.activationPrice && { activationPrice: params.activationPrice }), - ...(params.callbackRate && { callbackRate: params.callbackRate }), - ...(params.workingType && { workingType: params.workingType }), - ...(params.priceProtect !== undefined && { priceProtect: params.priceProtect }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ COIN-M Futures order placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || 'MARKET'}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place COIN-M order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Delivery futures symbol (e.g., BTCUSD_PERP, BTCUSD_240329)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for Hedge Mode. Use BOTH for One-Way Mode"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity in contracts"), + price: z.string().optional().describe("Limit price (required for LIMIT orders)"), + stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), + reduceOnly: z.boolean().optional().describe("Reduce position only"), + closePosition: z.boolean().optional().describe("Close entire position"), + activationPrice: z + .string() + .optional() + .describe("Activation price for TRAILING_STOP_MARKET"), + callbackRate: z + .string() + .optional() + .describe("Callback rate for TRAILING_STOP_MARKET (0.1% - 5%)"), + workingType: z + .enum(["MARK_PRICE", "CONTRACT_PRICE"]) + .optional() + .describe("Stop price trigger type"), + priceProtect: z.boolean().optional().describe("Price protection"), + newClientOrderId: z.string().optional().describe("Custom order ID"), + newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.newOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.closePosition !== undefined && { closePosition: params.closePosition }), + ...(params.activationPrice && { activationPrice: params.activationPrice }), + ...(params.callbackRate && { callbackRate: params.callbackRate }), + ...(params.workingType && { workingType: params.workingType }), + ...(params.priceProtect !== undefined && { priceProtect: params.priceProtect }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ COIN-M Futures order placed!\n\nOrder ID: ${data.orderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || "MARKET"}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place COIN-M order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/openOrder.ts b/src/tools/binance-futures-coinm/trade-api/openOrder.ts index f94278a3..8049b208 100644 --- a/src/tools/binance-futures-coinm/trade-api/openOrder.ts +++ b/src/tools/binance-futures-coinm/trade-api/openOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/openOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryOpenOrder(server: McpServer) { - server.tool( - "BinanceDeliveryOpenOrder", - "Query a single open COIN-M Futures order.", - { - symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await deliveryClient.restAPI.currentOpenOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📋 Open Order\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get open order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceDeliveryOpenOrder", + { + description: "Query a single open COIN-M Futures order.", + inputSchema: { + symbol: z.string().describe("Contract symbol (e.g., BTCUSD_PERP)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Error: Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await deliveryClient.restAPI.currentOpenOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📋 Open Order\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get open order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trade-api/openOrders.ts b/src/tools/binance-futures-coinm/trade-api/openOrders.ts index b5a7cf60..c166e66a 100644 --- a/src/tools/binance-futures-coinm/trade-api/openOrders.ts +++ b/src/tools/binance-futures-coinm/trade-api/openOrders.ts @@ -5,42 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/trade-api/openOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryOpenOrders(server: McpServer) { - server.tool( - "BinanceDeliveryOpenOrders", - "Get all current open COIN-M Futures orders.", - { - symbol: z.string().optional().describe("Contract symbol filter"), - pair: z.string().optional().describe("Filter by underlying pair"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.currentAllOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.pair && { pair: params.pair }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📋 Open Orders\n\nCount: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryOpenOrders", + { + description: "Get all current open COIN-M Futures orders.", + inputSchema: { + symbol: z.string().optional().describe("Contract symbol filter"), + pair: z.string().optional().describe("Filter by underlying pair"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.currentAllOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.pair && { pair: params.pair }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📋 Open Orders\n\nCount: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/trades.ts b/src/tools/binance-futures-coinm/trades.ts index 19dbb8e1..36eb277b 100644 --- a/src/tools/binance-futures-coinm/trades.ts +++ b/src/tools/binance-futures-coinm/trades.ts @@ -1,41 +1,48 @@ // src/tools/binance-futures-coinm/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMTrades(server: McpServer) { - server.tool( - "BinanceFuturesCOINMTrades", - "Get recent trades for a specific COIN-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMTrades", + { + description: "Get recent trades for a specific COIN-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await deliveryClient.trades(params); - const data = await deliveryClient.trades(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} recent trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} recent trades for COIN-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures recent trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures recent trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/userTrades.ts b/src/tools/binance-futures-coinm/userTrades.ts index 320c9842..66e1cbe9 100644 --- a/src/tools/binance-futures-coinm/userTrades.ts +++ b/src/tools/binance-futures-coinm/userTrades.ts @@ -1,53 +1,59 @@ // src/tools/binance-futures-coinm/userTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { deliveryClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesCOINMUserTrades(server: McpServer) { - server.tool( - "BinanceFuturesCOINMUserTrades", - "Get account trade list for COIN-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), - pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), - orderId: z.number().optional().describe("Filter by order ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - fromId: z.number().optional().describe("Trade ID to start from"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, pair, orderId, startTime, endTime, fromId, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (pair) params.pair = pair; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesCOINMUserTrades", + { + description: "Get account trade list for COIN-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSD_PERP)"), + pair: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + orderId: z.number().optional().describe("Filter by order ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + fromId: z.number().optional().describe("Trade ID to start from"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, pair, orderId, startTime, endTime, fromId, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (pair) params.pair = pair; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; - const data = await deliveryClient.userTrades(params); - + const data = await deliveryClient.userTrades(params); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} COIN-M Futures trades. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve COIN-M Futures user trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} COIN-M Futures trades. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: [ + { + type: "text", + text: `Failed to retrieve COIN-M Futures user trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-futures-coinm/userdatastream-api/closeListenKey.ts b/src/tools/binance-futures-coinm/userdatastream-api/closeListenKey.ts index bef5c09b..cebf3eaf 100644 --- a/src/tools/binance-futures-coinm/userdatastream-api/closeListenKey.ts +++ b/src/tools/binance-futures-coinm/userdatastream-api/closeListenKey.ts @@ -5,40 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/userdatastream-api/closeListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCloseListenKey(server: McpServer) { - server.tool( - "BinanceDeliveryCloseListenKey", - "Close a COIN-M Futures user data stream listen key.", - { - listenKey: z.string().optional().describe("Listen key to close"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.closeListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Listen Key Closed!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to close listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceDeliveryCloseListenKey", + { + description: "Close a COIN-M Futures user data stream listen key.", + inputSchema: { + listenKey: z.string().optional().describe("Listen key to close"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.closeListenKey({ + ...(params.listenKey && { listenKey: params.listenKey }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Listen Key Closed!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to close listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/userdatastream-api/createListenKey.ts b/src/tools/binance-futures-coinm/userdatastream-api/createListenKey.ts index 3684098c..07819f89 100644 --- a/src/tools/binance-futures-coinm/userdatastream-api/createListenKey.ts +++ b/src/tools/binance-futures-coinm/userdatastream-api/createListenKey.ts @@ -5,38 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/userdatastream-api/createListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryCreateListenKey(server: McpServer) { - server.tool( - "BinanceDeliveryCreateListenKey", + server.registerTool( + "BinanceDeliveryCreateListenKey", + { + description: "Create a new COIN-M Futures user data stream listen key. The listen key is valid for 60 minutes and can be used to receive account updates via WebSocket.", - { - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.createListenKey({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ COIN-M Listen Key Created!\n\nListen Key: ${data.listenKey}\n\n⚠️ Important:\n- Valid for 60 minutes\n- Use keepAlive endpoint to extend validity\n\nWebSocket URL: wss://dstream.binance.com/ws/${data.listenKey}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to create listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.createListenKey(); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ COIN-M Listen Key Created!\n\nListen Key: ${data.listenKey}\n\n⚠️ Important:\n- Valid for 60 minutes\n- Use keepAlive endpoint to extend validity\n\nWebSocket URL: wss://dstream.binance.com/ws/${data.listenKey}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to create listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-coinm/userdatastream-api/index.ts b/src/tools/binance-futures-coinm/userdatastream-api/index.ts index 7f0d2084..64281a93 100644 --- a/src/tools/binance-futures-coinm/userdatastream-api/index.ts +++ b/src/tools/binance-futures-coinm/userdatastream-api/index.ts @@ -5,14 +5,15 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/userdatastream-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceDeliveryCloseListenKey } from "./closeListenKey.js"; import { registerBinanceDeliveryCreateListenKey } from "./createListenKey.js"; import { registerBinanceDeliveryKeepAliveListenKey } from "./keepAliveListenKey.js"; -import { registerBinanceDeliveryCloseListenKey } from "./closeListenKey.js"; export function registerBinanceDeliveryUserDataStreamApiTools(server: McpServer) { - // User Data Stream (Listen Key) Management - registerBinanceDeliveryCreateListenKey(server); - registerBinanceDeliveryKeepAliveListenKey(server); - registerBinanceDeliveryCloseListenKey(server); + // User Data Stream (Listen Key) Management + registerBinanceDeliveryCreateListenKey(server); + registerBinanceDeliveryKeepAliveListenKey(server); + registerBinanceDeliveryCloseListenKey(server); } diff --git a/src/tools/binance-futures-coinm/userdatastream-api/keepAliveListenKey.ts b/src/tools/binance-futures-coinm/userdatastream-api/keepAliveListenKey.ts index e33c96ce..a9b5b60b 100644 --- a/src/tools/binance-futures-coinm/userdatastream-api/keepAliveListenKey.ts +++ b/src/tools/binance-futures-coinm/userdatastream-api/keepAliveListenKey.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-coinm/userdatastream-api/keepAliveListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { deliveryClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { deliveryClient } from "../../../config/binanceClient.js"; + export function registerBinanceDeliveryKeepAliveListenKey(server: McpServer) { - server.tool( - "BinanceDeliveryKeepAliveListenKey", + server.registerTool( + "BinanceDeliveryKeepAliveListenKey", + { + description: "Keep alive a COIN-M Futures user data stream listen key. Extends validity by 60 minutes. Should be called at least every 60 minutes to prevent timeout.", - { - listenKey: z.string().optional().describe("Listen key to keep alive"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await deliveryClient.restAPI.renewListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Listen Key Extended!\n\nYour COIN-M Futures listen key has been renewed for another 60 minutes.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to extend listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z.string().optional().describe("Listen key to keep alive"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await deliveryClient.restAPI.renewListenKey({ + ...(params.listenKey && { listenKey: params.listenKey }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Listen Key Extended!\n\nYour COIN-M Futures listen key has been renewed for another 60 minutes.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to extend listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/account.ts b/src/tools/binance-futures-usdm/account-api/account.ts index 87dd49c0..fbc5d989 100644 --- a/src/tools/binance-futures-usdm/account-api/account.ts +++ b/src/tools/binance-futures-usdm/account-api/account.ts @@ -5,36 +5,45 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/account.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesAccount(server: McpServer) { - server.tool( - "BinanceFuturesAccount", + server.registerTool( + "BinanceFuturesAccount", + { + description: "Get current USD-M Futures account information including positions, balances, and unrealized PnL.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.account({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures Account: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get account info: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.account({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures Account: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get account info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/adlQuantile.ts b/src/tools/binance-futures-usdm/account-api/adlQuantile.ts index 660332ba..8c737e01 100644 --- a/src/tools/binance-futures-usdm/account-api/adlQuantile.ts +++ b/src/tools/binance-futures-usdm/account-api/adlQuantile.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/adlQuantile.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesADLQuantile(server: McpServer) { - server.tool( - "BinanceFuturesADLQuantile", - "Get Position ADL (Auto-Deleveraging) Quantile estimation for USD-M Futures.", - { - symbol: z.string().optional().describe("Futures symbol"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.adlQuantile({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `ADL Quantile: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get ADL quantile: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesADLQuantile", + { + description: "Get Position ADL (Auto-Deleveraging) Quantile estimation for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.adlQuantile({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `ADL Quantile: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get ADL quantile: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/apiTradingStatus.ts b/src/tools/binance-futures-usdm/account-api/apiTradingStatus.ts index 052e84cb..ace208fd 100644 --- a/src/tools/binance-futures-usdm/account-api/apiTradingStatus.ts +++ b/src/tools/binance-futures-usdm/account-api/apiTradingStatus.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/apiTradingStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesApiTradingStatus(server: McpServer) { - server.tool( - "BinanceFuturesApiTradingStatus", - "Get API trading quantitative rules indicators for USD-M Futures.", - { - symbol: z.string().optional().describe("Futures symbol"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.apiTradingStatus({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `API Trading Status: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get API trading status: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesApiTradingStatus", + { + description: "Get API trading quantitative rules indicators for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.apiTradingStatus({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `API Trading Status: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get API trading status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/balance.ts b/src/tools/binance-futures-usdm/account-api/balance.ts index cfe28861..4c53a961 100644 --- a/src/tools/binance-futures-usdm/account-api/balance.ts +++ b/src/tools/binance-futures-usdm/account-api/balance.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/balance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesBalance(server: McpServer) { - server.tool( - "BinanceFuturesBalance", - "Get current USD-M Futures account balance information.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.balance({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures Balance: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get balance: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesBalance", + { + description: "Get current USD-M Futures account balance information.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.balance({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures Balance: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/commissionRate.ts b/src/tools/binance-futures-usdm/account-api/commissionRate.ts index 23045013..7b72c121 100644 --- a/src/tools/binance-futures-usdm/account-api/commissionRate.ts +++ b/src/tools/binance-futures-usdm/account-api/commissionRate.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/commissionRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCommissionRate(server: McpServer) { - server.tool( - "BinanceFuturesCommissionRate", - "Get user commission rate for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.commissionRate({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Commission Rate for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get commission rate: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesCommissionRate", + { + description: "Get user commission rate for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.commissionRate({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Commission Rate for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get commission rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/downloadId.ts b/src/tools/binance-futures-usdm/account-api/downloadId.ts index 3564cad8..034f3f92 100644 --- a/src/tools/binance-futures-usdm/account-api/downloadId.ts +++ b/src/tools/binance-futures-usdm/account-api/downloadId.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/downloadId.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesDownloadIdForFuturesTransactionHistory(server: McpServer) { - server.tool( - "BinanceFuturesDownloadId", - "Get download ID for USD-M Futures transaction history.", - { - startTime: z.number().int().describe("Start timestamp in ms"), - endTime: z.number().int().describe("End timestamp in ms"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.downloadIdForFuturesTransactionHistory({ - startTime: params.startTime, - endTime: params.endTime, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Download ID: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get download ID: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesDownloadId", + { + description: "Get download ID for USD-M Futures transaction history.", + inputSchema: { + startTime: z.number().int().describe("Start timestamp in ms"), + endTime: z.number().int().describe("End timestamp in ms"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.downloadIdForFuturesTransactionHistory({ + startTime: params.startTime, + endTime: params.endTime, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Download ID: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get download ID: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/forceOrders.ts b/src/tools/binance-futures-usdm/account-api/forceOrders.ts index 8ca69f88..87c6d293 100644 --- a/src/tools/binance-futures-usdm/account-api/forceOrders.ts +++ b/src/tools/binance-futures-usdm/account-api/forceOrders.ts @@ -5,46 +5,54 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/forceOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesForceOrders(server: McpServer) { - server.tool( - "BinanceFuturesForceOrders", - "Get user's force orders (liquidation orders) for USD-M Futures.", - { - symbol: z.string().optional().describe("Futures symbol"), - autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("Type of force order"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of results. Default 50, max 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.forceOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.autoCloseType && { autoCloseType: params.autoCloseType }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Force Orders: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get force orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesForceOrders", + { + description: "Get user's force orders (liquidation orders) for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol"), + autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("Type of force order"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of results. Default 50, max 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.forceOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.autoCloseType && { autoCloseType: params.autoCloseType }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Force Orders: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get force orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/income.ts b/src/tools/binance-futures-usdm/account-api/income.ts index f9e61e12..1fcb8273 100644 --- a/src/tools/binance-futures-usdm/account-api/income.ts +++ b/src/tools/binance-futures-usdm/account-api/income.ts @@ -5,52 +5,77 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/income.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesIncome(server: McpServer) { - server.tool( - "BinanceFuturesIncome", - "Get income history for USD-M Futures account.", - { - symbol: z.string().optional().describe("Futures symbol"), - incomeType: z.enum([ - "TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", - "COMMISSION", "INSURANCE_CLEAR", "REFERRAL_KICKBACK", "COMMISSION_REBATE", - "API_REBATE", "CONTEST_REWARD", "CROSS_COLLATERAL_TRANSFER", "OPTIONS_PREMIUM_FEE", - "OPTIONS_SETTLE_PROFIT", "INTERNAL_TRANSFER", "AUTO_EXCHANGE", "DELIVERED_SETTELMENT", - "COIN_SWAP_DEPOSIT", "COIN_SWAP_WITHDRAW", "POSITION_LIMIT_INCREASE_FEE" - ]).optional().describe("Type of income"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of results. Default 100, max 1000"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.income({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.incomeType && { incomeType: params.incomeType }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Income History: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get income history: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesIncome", + { + description: "Get income history for USD-M Futures account.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol"), + incomeType: z + .enum([ + "TRANSFER", + "WELCOME_BONUS", + "REALIZED_PNL", + "FUNDING_FEE", + "COMMISSION", + "INSURANCE_CLEAR", + "REFERRAL_KICKBACK", + "COMMISSION_REBATE", + "API_REBATE", + "CONTEST_REWARD", + "CROSS_COLLATERAL_TRANSFER", + "OPTIONS_PREMIUM_FEE", + "OPTIONS_SETTLE_PROFIT", + "INTERNAL_TRANSFER", + "AUTO_EXCHANGE", + "DELIVERED_SETTELMENT", + "COIN_SWAP_DEPOSIT", + "COIN_SWAP_WITHDRAW", + "POSITION_LIMIT_INCREASE_FEE", + ]) + .optional() + .describe("Type of income"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of results. Default 100, max 1000"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.income({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.incomeType && { incomeType: params.incomeType }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Income History: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get income history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/index.ts b/src/tools/binance-futures-usdm/account-api/index.ts index 907beb62..3a63c68b 100644 --- a/src/tools/binance-futures-usdm/account-api/index.ts +++ b/src/tools/binance-futures-usdm/account-api/index.ts @@ -5,48 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFuturesAccount } from "./account.js"; -import { registerBinanceFuturesBalance } from "./balance.js"; -import { registerBinanceFuturesPositionRisk } from "./positionRisk.js"; -import { registerBinanceFuturesUserTrades } from "./userTrades.js"; -import { registerBinanceFuturesIncome } from "./income.js"; -import { registerBinanceFuturesLeverageBracket } from "./leverageBracket.js"; import { registerBinanceFuturesADLQuantile } from "./adlQuantile.js"; -import { registerBinanceFuturesForceOrders } from "./forceOrders.js"; import { registerBinanceFuturesApiTradingStatus } from "./apiTradingStatus.js"; +import { registerBinanceFuturesBalance } from "./balance.js"; import { registerBinanceFuturesCommissionRate } from "./commissionRate.js"; import { registerBinanceFuturesDownloadIdForFuturesTransactionHistory } from "./downloadId.js"; -import { registerBinanceFuturesPositionMode } from "./positionMode.js"; -import { registerBinanceFuturesMultiAssetsMode } from "./multiAssetsMode.js"; +import { registerBinanceFuturesForceOrders } from "./forceOrders.js"; +import { registerBinanceFuturesIncome } from "./income.js"; import { registerBinanceFuturesLeverage } from "./leverage.js"; +import { registerBinanceFuturesLeverageBracket } from "./leverageBracket.js"; import { registerBinanceFuturesMarginType } from "./marginType.js"; +import { registerBinanceFuturesMultiAssetsMode } from "./multiAssetsMode.js"; import { registerBinanceFuturesPositionMargin } from "./positionMargin.js"; +import { registerBinanceFuturesPositionMode } from "./positionMode.js"; +import { registerBinanceFuturesPositionRisk } from "./positionRisk.js"; +import { registerBinanceFuturesUserTrades } from "./userTrades.js"; export function registerBinanceFuturesAccountApiTools(server: McpServer) { - // Account Info - registerBinanceFuturesAccount(server); - registerBinanceFuturesBalance(server); - registerBinanceFuturesPositionRisk(server); - registerBinanceFuturesPositionMode(server); - registerBinanceFuturesMultiAssetsMode(server); - - // Leverage & Margin - registerBinanceFuturesLeverage(server); - registerBinanceFuturesMarginType(server); - registerBinanceFuturesPositionMargin(server); - - // Trades & History - registerBinanceFuturesUserTrades(server); - registerBinanceFuturesIncome(server); - registerBinanceFuturesForceOrders(server); - registerBinanceFuturesDownloadIdForFuturesTransactionHistory(server); - - // Risk & Limits - registerBinanceFuturesLeverageBracket(server); - registerBinanceFuturesADLQuantile(server); - - // Status & Commission - registerBinanceFuturesApiTradingStatus(server); - registerBinanceFuturesCommissionRate(server); + // Account Info + registerBinanceFuturesAccount(server); + registerBinanceFuturesBalance(server); + registerBinanceFuturesPositionRisk(server); + registerBinanceFuturesPositionMode(server); + registerBinanceFuturesMultiAssetsMode(server); + + // Leverage & Margin + registerBinanceFuturesLeverage(server); + registerBinanceFuturesMarginType(server); + registerBinanceFuturesPositionMargin(server); + + // Trades & History + registerBinanceFuturesUserTrades(server); + registerBinanceFuturesIncome(server); + registerBinanceFuturesForceOrders(server); + registerBinanceFuturesDownloadIdForFuturesTransactionHistory(server); + + // Risk & Limits + registerBinanceFuturesLeverageBracket(server); + registerBinanceFuturesADLQuantile(server); + + // Status & Commission + registerBinanceFuturesApiTradingStatus(server); + registerBinanceFuturesCommissionRate(server); } diff --git a/src/tools/binance-futures-usdm/account-api/leverage.ts b/src/tools/binance-futures-usdm/account-api/leverage.ts index 1820abc3..21a751e1 100644 --- a/src/tools/binance-futures-usdm/account-api/leverage.ts +++ b/src/tools/binance-futures-usdm/account-api/leverage.ts @@ -5,40 +5,54 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/leverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesLeverage(server: McpServer) { - server.tool( - "BinanceFuturesChangeLeverage", + server.registerTool( + "BinanceFuturesChangeLeverage", + { + description: "Change initial leverage for a USD-M Futures symbol. ⚠️ Leverage changes affect your liquidation price and margin requirements.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125, varies by symbol)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changeInitialLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Leverage changed for ${params.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to change leverage: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + leverage: z + .number() + .int() + .min(1) + .max(125) + .describe("Target leverage (1-125, varies by symbol)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changeInitialLeverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Leverage changed for ${params.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to change leverage: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/leverageBracket.ts b/src/tools/binance-futures-usdm/account-api/leverageBracket.ts index 1f091764..0e1ed30a 100644 --- a/src/tools/binance-futures-usdm/account-api/leverageBracket.ts +++ b/src/tools/binance-futures-usdm/account-api/leverageBracket.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/leverageBracket.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesLeverageBracket(server: McpServer) { - server.tool( - "BinanceFuturesLeverageBracket", - "Get notional and leverage brackets for USD-M Futures symbols.", - { - symbol: z.string().optional().describe("Futures symbol. If omitted, returns all"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.leverageBracket({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Leverage Brackets: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get leverage brackets: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesLeverageBracket", + { + description: "Get notional and leverage brackets for USD-M Futures symbols.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol. If omitted, returns all"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.leverageBracket({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Leverage Brackets: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get leverage brackets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/marginType.ts b/src/tools/binance-futures-usdm/account-api/marginType.ts index 9b283fb8..a4896b30 100644 --- a/src/tools/binance-futures-usdm/account-api/marginType.ts +++ b/src/tools/binance-futures-usdm/account-api/marginType.ts @@ -5,40 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/marginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesMarginType(server: McpServer) { - server.tool( - "BinanceFuturesChangeMarginType", + server.registerTool( + "BinanceFuturesChangeMarginType", + { + description: "Change margin type between ISOLATED and CROSSED for a USD-M Futures symbol. ⚠️ Cannot change if you have existing positions or open orders.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changeMarginType({ - symbol: params.symbol, - marginType: params.marginType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Margin type changed for ${params.symbol} to ${params.marginType}\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to change margin type: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changeMarginType({ + symbol: params.symbol, + marginType: params.marginType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Margin type changed for ${params.symbol} to ${params.marginType}\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to change margin type: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/multiAssetsMode.ts b/src/tools/binance-futures-usdm/account-api/multiAssetsMode.ts index f6453d55..f9381d9e 100644 --- a/src/tools/binance-futures-usdm/account-api/multiAssetsMode.ts +++ b/src/tools/binance-futures-usdm/account-api/multiAssetsMode.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/multiAssetsMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesMultiAssetsMode(server: McpServer) { - server.tool( - "BinanceFuturesGetMultiAssetsMode", - "Get current Multi-Assets Mode for USD-M Futures.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.getMultiAssetsMode({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Multi-Assets Mode: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get multi-assets mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesGetMultiAssetsMode", + { + description: "Get current Multi-Assets Mode for USD-M Futures.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.getMultiAssetsMode({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Multi-Assets Mode: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get multi-assets mode: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/positionMargin.ts b/src/tools/binance-futures-usdm/account-api/positionMargin.ts index e4c6b518..bf51dd49 100644 --- a/src/tools/binance-futures-usdm/account-api/positionMargin.ts +++ b/src/tools/binance-futures-usdm/account-api/positionMargin.ts @@ -5,84 +5,103 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/positionMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesPositionMargin(server: McpServer) { - // Modify Isolated Position Margin - server.tool( - "BinanceFuturesModifyPositionMargin", - "Add or reduce margin for an isolated position in USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - amount: z.string().describe("Amount of margin to add (positive) or remove (negative)"), - type: z.enum(["1", "2"]).describe("1: Add margin, 2: Reduce margin"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.modifyIsolatedPositionMargin({ - symbol: params.symbol, - amount: params.amount, - type: parseInt(params.type), - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `✅ Position margin modified for ${params.symbol}\nAmount: ${params.amount}\nType: ${params.type === "1" ? "Added" : "Reduced"}\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to modify position margin: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // Get Position Margin Change History - server.tool( - "BinanceFuturesGetPositionMarginHistory", - "Get position margin change history for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - type: z.enum(["1", "2"]).optional().describe("1: Add margin, 2: Reduce margin"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 500"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.getPositionMarginChangeHistory({ - symbol: params.symbol, - ...(params.type && { type: parseInt(params.type) }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Position margin history for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get position margin history: ${errorMessage}` }], - isError: true - }; - } - } - ); + // Modify Isolated Position Margin + server.registerTool( + "BinanceFuturesModifyPositionMargin", + { + description: "Add or reduce margin for an isolated position in USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + amount: z.string().describe("Amount of margin to add (positive) or remove (negative)"), + type: z.enum(["1", "2"]).describe("1: Add margin, 2: Reduce margin"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for Hedge Mode"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.modifyIsolatedPositionMargin({ + symbol: params.symbol, + amount: params.amount, + type: parseInt(params.type), + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Position margin modified for ${params.symbol}\nAmount: ${params.amount}\nType: ${params.type === "1" ? "Added" : "Reduced"}\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to modify position margin: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // Get Position Margin Change History + server.registerTool( + "BinanceFuturesGetPositionMarginHistory", + { + description: "Get position margin change history for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + type: z.enum(["1", "2"]).optional().describe("1: Add margin, 2: Reduce margin"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z.number().int().max(500).optional().describe("Number of records. Default 500"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.getPositionMarginChangeHistory({ + symbol: params.symbol, + ...(params.type && { type: parseInt(params.type) }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Position margin history for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get position margin history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/positionMode.ts b/src/tools/binance-futures-usdm/account-api/positionMode.ts index ac44d5ad..a4c88bcb 100644 --- a/src/tools/binance-futures-usdm/account-api/positionMode.ts +++ b/src/tools/binance-futures-usdm/account-api/positionMode.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/positionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesPositionMode(server: McpServer) { - server.tool( - "BinanceFuturesGetPositionMode", - "Get current position mode (Hedge Mode or One-way Mode) for USD-M Futures.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.getPositionMode({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Position Mode: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get position mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesGetPositionMode", + { + description: "Get current position mode (Hedge Mode or One-way Mode) for USD-M Futures.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.getPositionMode({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Position Mode: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get position mode: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/positionRisk.ts b/src/tools/binance-futures-usdm/account-api/positionRisk.ts index 581c6930..9158c4cc 100644 --- a/src/tools/binance-futures-usdm/account-api/positionRisk.ts +++ b/src/tools/binance-futures-usdm/account-api/positionRisk.ts @@ -5,38 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/positionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesPositionRisk(server: McpServer) { - server.tool( - "BinanceFuturesPositionRisk", - "Get current position information for USD-M Futures.", - { - symbol: z.string().optional().describe("Futures symbol. If omitted, returns all positions"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.positionRisk({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Position Risk: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get position risk: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesPositionRisk", + { + description: "Get current position information for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol. If omitted, returns all positions"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.positionRisk({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Position Risk: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get position risk: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account-api/userTrades.ts b/src/tools/binance-futures-usdm/account-api/userTrades.ts index 5d02d386..90257611 100644 --- a/src/tools/binance-futures-usdm/account-api/userTrades.ts +++ b/src/tools/binance-futures-usdm/account-api/userTrades.ts @@ -5,48 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/account-api/userTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesUserTrades(server: McpServer) { - server.tool( - "BinanceFuturesUserTrades", - "Get trades for a specific USD-M Futures account and symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID to filter trades"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().optional().describe("Number of results. Default 500, max 1000"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.userTrades({ - symbol: params.symbol, - ...(params.orderId !== undefined && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId !== undefined && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `User Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get user trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesUserTrades", + { + description: "Get trades for a specific USD-M Futures account and symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID to filter trades"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z.number().int().optional().describe("Number of results. Default 500, max 1000"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.userTrades({ + symbol: params.symbol, + ...(params.orderId !== undefined && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId !== undefined && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `User Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get user trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/account.ts b/src/tools/binance-futures-usdm/account.ts index 5fa4ef7a..beccd190 100644 --- a/src/tools/binance-futures-usdm/account.ts +++ b/src/tools/binance-futures-usdm/account.ts @@ -1,33 +1,37 @@ // src/tools/binance-futures-usdm/account.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMAccount(server: McpServer) { - server.tool( - "BinanceFuturesUSDMAccount", + server.registerTool( + "BinanceFuturesUSDMAccount", + { + description: "Get current USD-M Futures account information including positions and balances.", - {}, - async () => { - try { - const data = await futuresClient.account(); + }, + async () => { + try { + const data = await futuresClient.account(); + + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures account information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures account information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/adlQuantile.ts b/src/tools/binance-futures-usdm/adlQuantile.ts index 3f743b0e..c9069996 100644 --- a/src/tools/binance-futures-usdm/adlQuantile.ts +++ b/src/tools/binance-futures-usdm/adlQuantile.ts @@ -1,39 +1,52 @@ // src/tools/binance-futures-usdm/adlQuantile.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMADLQuantile(server: McpServer) { - server.tool( - "BinanceFuturesUSDMADLQuantile", - "Get position ADL (Auto-Deleveraging) quantile estimate for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all positions") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMADLQuantile", + { + description: "Get position ADL (Auto-Deleveraging) quantile estimate for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all positions", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.adlQuantile(params); - const data = await futuresClient.adlQuantile(params); + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures ADL quantile${symbol ? ` for ${symbol}` : " for all positions"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures ADL quantile${symbol ? ` for ${symbol}` : ' for all positions'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures ADL quantile: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures ADL quantile: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/aggTrades.ts b/src/tools/binance-futures-usdm/aggTrades.ts index 6ea6bc9b..f3e70103 100644 --- a/src/tools/binance-futures-usdm/aggTrades.ts +++ b/src/tools/binance-futures-usdm/aggTrades.ts @@ -1,46 +1,60 @@ // src/tools/binance-futures-usdm/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMAggTrades(server: McpServer) { - server.tool( - "BinanceFuturesUSDMAggTrades", - "Get compressed, aggregate trades for a specific USD-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - fromId: z.number().optional().describe("ID to get aggregate trades from INCLUSIVE"), - startTime: z.number().optional().describe("Timestamp in ms to get aggregate trades from INCLUSIVE"), - endTime: z.number().optional().describe("Timestamp in ms to get aggregate trades until INCLUSIVE"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMAggTrades", + { + description: "Get compressed, aggregate trades for a specific USD-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + fromId: z.number().optional().describe("ID to get aggregate trades from INCLUSIVE"), + startTime: z + .number() + .optional() + .describe("Timestamp in ms to get aggregate trades from INCLUSIVE"), + endTime: z + .number() + .optional() + .describe("Timestamp in ms to get aggregate trades until INCLUSIVE"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.aggTrades(params); - const data = await futuresClient.aggTrades(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} aggregated trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} aggregated trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures aggregated trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures aggregated trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/allOrders.ts b/src/tools/binance-futures-usdm/allOrders.ts index 9b5bdeb3..85299f53 100644 --- a/src/tools/binance-futures-usdm/allOrders.ts +++ b/src/tools/binance-futures-usdm/allOrders.ts @@ -1,46 +1,51 @@ // src/tools/binance-futures-usdm/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMAllOrders", - "Get all orders (active, canceled, or filled) for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID to start from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, orderId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMAllOrders", + { + description: "Get all orders (active, canceled, or filled) for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID to start from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, orderId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.allOrders(params); - const data = await futuresClient.allOrders(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} USD-M Futures orders for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} USD-M Futures orders for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures all orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures all orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/balance.ts b/src/tools/binance-futures-usdm/balance.ts index 9b6397e9..272160fc 100644 --- a/src/tools/binance-futures-usdm/balance.ts +++ b/src/tools/binance-futures-usdm/balance.ts @@ -1,33 +1,34 @@ // src/tools/binance-futures-usdm/balance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMBalance(server: McpServer) { - server.tool( - "BinanceFuturesUSDMBalance", - "Get current USD-M Futures account balance.", - {}, - async () => { - try { - const data = await futuresClient.balance(); + server.registerTool( + "BinanceFuturesUSDMBalance", + { description: "Get current USD-M Futures account balance." }, + async () => { + try { + const data = await futuresClient.balance(); + + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures account balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures account balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/batchOrders.ts b/src/tools/binance-futures-usdm/batchOrders.ts index 181f6235..cb0744a5 100644 --- a/src/tools/binance-futures-usdm/batchOrders.ts +++ b/src/tools/binance-futures-usdm/batchOrders.ts @@ -1,36 +1,45 @@ // src/tools/binance-futures-usdm/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMBatchOrders", - "Place multiple orders for USD-M Futures (max 5 orders).", - { - batchOrders: z.string().describe("JSON string of order list. Max 5 orders. Each order has: symbol, side, type, and optional parameters like positionSide, timeInForce, quantity, reduceOnly, price, newClientOrderId, stopPrice, activationPrice, callbackRate, workingType, priceProtect") - }, - async ({ batchOrders }) => { - try { - const data = await futuresClient.batchOrders({ batchOrders }); + server.registerTool( + "BinanceFuturesUSDMBatchOrders", + { + description: "Place multiple orders for USD-M Futures (max 5 orders).", + inputSchema: { + batchOrders: z + .string() + .describe( + "JSON string of order list. Max 5 orders. Each order has: symbol, side, type, and optional parameters like positionSide, timeInForce, quantity, reduceOnly, price, newClientOrderId, stopPrice, activationPrice, callbackRate, workingType, priceProtect", + ), + }, + }, + async ({ batchOrders }) => { + try { + const data = await futuresClient.batchOrders({ batchOrders }); + + return { + content: [ + { + type: "text", + text: `USD-M Futures batch orders created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures batch orders created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create USD-M Futures batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create USD-M Futures batch orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/bookTicker.ts b/src/tools/binance-futures-usdm/bookTicker.ts index 18581845..1e58188f 100644 --- a/src/tools/binance-futures-usdm/bookTicker.ts +++ b/src/tools/binance-futures-usdm/bookTicker.ts @@ -1,39 +1,50 @@ // src/tools/binance-futures-usdm/bookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMBookTicker(server: McpServer) { - server.tool( - "BinanceFuturesUSDMBookTicker", + server.registerTool( + "BinanceFuturesUSDMBookTicker", + { + description: "Get best price/qty on the order book for a symbol or symbols for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.bookTicker(params); - const data = await futuresClient.bookTicker(params); + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures book ticker${symbol ? ` for ${symbol}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures book ticker${symbol ? ` for ${symbol}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures book ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures book ticker: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/cancelAllOrders.ts b/src/tools/binance-futures-usdm/cancelAllOrders.ts index 631fb095..8323cea0 100644 --- a/src/tools/binance-futures-usdm/cancelAllOrders.ts +++ b/src/tools/binance-futures-usdm/cancelAllOrders.ts @@ -1,36 +1,41 @@ // src/tools/binance-futures-usdm/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMCancelAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMCancelAllOrders", - "Cancel all open orders for a symbol in USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const data = await futuresClient.cancelAllOpenOrders({ symbol }); + server.registerTool( + "BinanceFuturesUSDMCancelAllOrders", + { + description: "Cancel all open orders for a symbol in USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const data = await futuresClient.cancelAllOpenOrders({ symbol }); + + return { + content: [ + { + type: "text", + text: `All USD-M Futures open orders cancelled for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `All USD-M Futures open orders cancelled for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel USD-M Futures open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to cancel USD-M Futures open orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/cancelBatchOrders.ts b/src/tools/binance-futures-usdm/cancelBatchOrders.ts index 394847a1..a1ebabe4 100644 --- a/src/tools/binance-futures-usdm/cancelBatchOrders.ts +++ b/src/tools/binance-futures-usdm/cancelBatchOrders.ts @@ -1,42 +1,50 @@ // src/tools/binance-futures-usdm/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMCancelBatchOrders", - "Cancel multiple orders for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderIdList: z.string().optional().describe("Comma-separated list of order IDs (max 10)"), - origClientOrderIdList: z.string().optional().describe("Comma-separated list of client order IDs (max 10)") - }, - async ({ symbol, orderIdList, origClientOrderIdList }) => { - try { - const params: any = { symbol }; - if (orderIdList) params.orderIdList = orderIdList; - if (origClientOrderIdList) params.origClientOrderIdList = origClientOrderIdList; + server.registerTool( + "BinanceFuturesUSDMCancelBatchOrders", + { + description: "Cancel multiple orders for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderIdList: z.string().optional().describe("Comma-separated list of order IDs (max 10)"), + origClientOrderIdList: z + .string() + .optional() + .describe("Comma-separated list of client order IDs (max 10)"), + }, + }, + async ({ symbol, orderIdList, origClientOrderIdList }) => { + try { + const params: any = { symbol }; + if (orderIdList) params.orderIdList = orderIdList; + if (origClientOrderIdList) params.origClientOrderIdList = origClientOrderIdList; + + const data = await futuresClient.cancelBatchOrders(params); - const data = await futuresClient.cancelBatchOrders(params); + return { + content: [ + { + type: "text", + text: `USD-M Futures batch orders cancelled. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures batch orders cancelled. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel USD-M Futures batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to cancel USD-M Futures batch orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/cancelOrder.ts b/src/tools/binance-futures-usdm/cancelOrder.ts index a4e3eb8e..d2285206 100644 --- a/src/tools/binance-futures-usdm/cancelOrder.ts +++ b/src/tools/binance-futures-usdm/cancelOrder.ts @@ -1,42 +1,47 @@ // src/tools/binance-futures-usdm/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMCancelOrder(server: McpServer) { - server.tool( - "BinanceFuturesUSDMCancelOrder", - "Cancel an existing order for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; + server.registerTool( + "BinanceFuturesUSDMCancelOrder", + { + description: "Cancel an existing order for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const data = await futuresClient.cancelOrder(params); - const data = await futuresClient.cancelOrder(params); + return { + content: [ + { + type: "text", + text: `USD-M Futures order cancelled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures order cancelled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel USD-M Futures order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to cancel USD-M Futures order: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/commissionRate.ts b/src/tools/binance-futures-usdm/commissionRate.ts index 328297c4..b81c8b85 100644 --- a/src/tools/binance-futures-usdm/commissionRate.ts +++ b/src/tools/binance-futures-usdm/commissionRate.ts @@ -1,36 +1,44 @@ // src/tools/binance-futures-usdm/commissionRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMCommissionRate(server: McpServer) { - server.tool( - "BinanceFuturesUSDMCommissionRate", - "Get user commission rate for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const data = await futuresClient.commissionRate({ symbol }); + server.registerTool( + "BinanceFuturesUSDMCommissionRate", + { + description: "Get user commission rate for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const data = await futuresClient.commissionRate({ symbol }); + + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures commission rate for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures commission rate for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures commission rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures commission rate: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/continuousKlines.ts b/src/tools/binance-futures-usdm/continuousKlines.ts index 358f278c..41ddebee 100644 --- a/src/tools/binance-futures-usdm/continuousKlines.ts +++ b/src/tools/binance-futures-usdm/continuousKlines.ts @@ -1,48 +1,74 @@ // src/tools/binance-futures-usdm/continuousKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMContinuousKlines(server: McpServer) { - server.tool( - "BinanceFuturesUSDMContinuousKlines", - "Get continuous contract Kline/candlestick data for USD-M Futures.", - { - pair: z.string().describe("Trading pair (e.g., BTCUSDT)"), - contractType: z.enum(["PERPETUAL", "CURRENT_MONTH", "NEXT_MONTH", "CURRENT_QUARTER", "NEXT_QUARTER"]).describe("Contract type"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ pair, contractType, interval, startTime, endTime, limit }) => { - try { - const params: any = { pair, contractType, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMContinuousKlines", + { + description: "Get continuous contract Kline/candlestick data for USD-M Futures.", + inputSchema: { + pair: z.string().describe("Trading pair (e.g., BTCUSDT)"), + contractType: z + .enum(["PERPETUAL", "CURRENT_MONTH", "NEXT_MONTH", "CURRENT_QUARTER", "NEXT_QUARTER"]) + .describe("Contract type"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ pair, contractType, interval, startTime, endTime, limit }) => { + try { + const params: any = { pair, contractType, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.continuousKlines(params); - const data = await futuresClient.continuousKlines(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} continuous klines for USD-M Futures ${pair} ${contractType} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} continuous klines for USD-M Futures ${pair} ${contractType} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures continuous klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures continuous klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/depth.ts b/src/tools/binance-futures-usdm/depth.ts index f477687d..1cb17135 100644 --- a/src/tools/binance-futures-usdm/depth.ts +++ b/src/tools/binance-futures-usdm/depth.ts @@ -1,40 +1,53 @@ // src/tools/binance-futures-usdm/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMDepth(server: McpServer) { - server.tool( - "BinanceFuturesUSDMDepth", - "Get order book depth data for a specific USD-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Depth of the order book. Default 500; max 1000. Valid limits: [5, 10, 20, 50, 100, 500, 1000]") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMDepth", + { + description: "Get order book depth data for a specific USD-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z + .number() + .optional() + .describe( + "Depth of the order book. Default 500; max 1000. Valid limits: [5, 10, 20, 50, 100, 500, 1000]", + ), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.depth(params); - const data = await futuresClient.depth(params); + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures order book depth: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures order book depth: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/exchangeInfo.ts b/src/tools/binance-futures-usdm/exchangeInfo.ts index 12640958..ebc8c483 100644 --- a/src/tools/binance-futures-usdm/exchangeInfo.ts +++ b/src/tools/binance-futures-usdm/exchangeInfo.ts @@ -1,32 +1,34 @@ // src/tools/binance-futures-usdm/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMExchangeInfo(server: McpServer) { - server.tool( - "BinanceFuturesUSDMExchangeInfo", - "Get current exchange trading rules and symbol information for USD-M Futures.", - {}, - async () => { - try { - const data = await futuresClient.exchangeInfo(); - return { - content: [ - { - type: "text", - text: `USD-M Futures exchange info retrieved. Symbols count: ${data.symbols?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get USD-M Futures exchange info: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesUSDMExchangeInfo", + { description: "Get current exchange trading rules and symbol information for USD-M Futures." }, + async () => { + try { + const data = await futuresClient.exchangeInfo(); + + return { + content: [ + { + type: "text", + text: `USD-M Futures exchange info retrieved. Symbols count: ${data.symbols?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get USD-M Futures exchange info: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/forceOrders.ts b/src/tools/binance-futures-usdm/forceOrders.ts index d07e5f32..bf78b05f 100644 --- a/src/tools/binance-futures-usdm/forceOrders.ts +++ b/src/tools/binance-futures-usdm/forceOrders.ts @@ -1,47 +1,58 @@ // src/tools/binance-futures-usdm/forceOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMForceOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMForceOrders", - "Get user force orders (liquidation orders) for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - autoCloseType: z.enum(["LIQUIDATION", "ADL"]).optional().describe("Auto close type: LIQUIDATION or ADL"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 50; max 100") - }, - async ({ symbol, autoCloseType, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (autoCloseType) params.autoCloseType = autoCloseType; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMForceOrders", + { + description: "Get user force orders (liquidation orders) for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + autoCloseType: z + .enum(["LIQUIDATION", "ADL"]) + .optional() + .describe("Auto close type: LIQUIDATION or ADL"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 50; max 100"), + }, + }, + async ({ symbol, autoCloseType, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (autoCloseType) params.autoCloseType = autoCloseType; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.forceOrders(params); - const data = await futuresClient.forceOrders(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} USD-M Futures force orders. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} USD-M Futures force orders. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures force orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures force orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/fundingRate.ts b/src/tools/binance-futures-usdm/fundingRate.ts index 7dcf18d6..f1fcfcdf 100644 --- a/src/tools/binance-futures-usdm/fundingRate.ts +++ b/src/tools/binance-futures-usdm/fundingRate.ts @@ -1,45 +1,53 @@ // src/tools/binance-futures-usdm/fundingRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMFundingRate(server: McpServer) { - server.tool( - "BinanceFuturesUSDMFundingRate", - "Get funding rate history for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 100; max 1000") - }, - async ({ symbol, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMFundingRate", + { + description: "Get funding rate history for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 100; max 1000"), + }, + }, + async ({ symbol, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.fundingRate(params); - const data = await futuresClient.fundingRate(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} funding rate records for USD-M Futures${symbol ? ` ${symbol}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} funding rate records for USD-M Futures${symbol ? ` ${symbol}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures funding rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures funding rate: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/getOrder.ts b/src/tools/binance-futures-usdm/getOrder.ts index 08922276..2c4807d7 100644 --- a/src/tools/binance-futures-usdm/getOrder.ts +++ b/src/tools/binance-futures-usdm/getOrder.ts @@ -1,42 +1,47 @@ // src/tools/binance-futures-usdm/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMGetOrder(server: McpServer) { - server.tool( - "BinanceFuturesUSDMGetOrder", - "Query an existing order for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; + server.registerTool( + "BinanceFuturesUSDMGetOrder", + { + description: "Query an existing order for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const data = await futuresClient.getOrder(params); - const data = await futuresClient.getOrder(params); + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures order. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures order. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures order: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/historicalTrades.ts b/src/tools/binance-futures-usdm/historicalTrades.ts index 7035b792..f93bc093 100644 --- a/src/tools/binance-futures-usdm/historicalTrades.ts +++ b/src/tools/binance-futures-usdm/historicalTrades.ts @@ -1,42 +1,53 @@ // src/tools/binance-futures-usdm/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMHistoricalTrades(server: McpServer) { - server.tool( - "BinanceFuturesUSDMHistoricalTrades", - "Get older market historical trades for a specific USD-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), - fromId: z.number().optional().describe("Trade ID to fetch from. Default gets most recent trades") - }, - async ({ symbol, limit, fromId }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - if (fromId !== undefined) params.fromId = fromId; + server.registerTool( + "BinanceFuturesUSDMHistoricalTrades", + { + description: "Get older market historical trades for a specific USD-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), + fromId: z + .number() + .optional() + .describe("Trade ID to fetch from. Default gets most recent trades"), + }, + }, + async ({ symbol, limit, fromId }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + if (fromId !== undefined) params.fromId = fromId; + + const data = await futuresClient.historicalTrades(params); - const data = await futuresClient.historicalTrades(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} historical trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} historical trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures historical trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures historical trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/income.ts b/src/tools/binance-futures-usdm/income.ts index 6cd925d5..c6e183b6 100644 --- a/src/tools/binance-futures-usdm/income.ts +++ b/src/tools/binance-futures-usdm/income.ts @@ -1,47 +1,75 @@ // src/tools/binance-futures-usdm/income.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMIncome(server: McpServer) { - server.tool( - "BinanceFuturesUSDMIncome", - "Get income history for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - incomeType: z.enum(["TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", "COMMISSION", "INSURANCE_CLEAR", "REFERRAL_KICKBACK", "COMMISSION_REBATE", "API_REBATE", "CONTEST_REWARD", "CROSS_COLLATERAL_TRANSFER", "OPTIONS_PREMIUM_FEE", "OPTIONS_SETTLE_PROFIT", "INTERNAL_TRANSFER", "AUTO_EXCHANGE", "DELIVERED_SETTELMENT", "COIN_SWAP_DEPOSIT", "COIN_SWAP_WITHDRAW", "POSITION_LIMIT_INCREASE_FEE"]).optional().describe("Income type"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 100; max 1000") - }, - async ({ symbol, incomeType, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (incomeType) params.incomeType = incomeType; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMIncome", + { + description: "Get income history for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + incomeType: z + .enum([ + "TRANSFER", + "WELCOME_BONUS", + "REALIZED_PNL", + "FUNDING_FEE", + "COMMISSION", + "INSURANCE_CLEAR", + "REFERRAL_KICKBACK", + "COMMISSION_REBATE", + "API_REBATE", + "CONTEST_REWARD", + "CROSS_COLLATERAL_TRANSFER", + "OPTIONS_PREMIUM_FEE", + "OPTIONS_SETTLE_PROFIT", + "INTERNAL_TRANSFER", + "AUTO_EXCHANGE", + "DELIVERED_SETTELMENT", + "COIN_SWAP_DEPOSIT", + "COIN_SWAP_WITHDRAW", + "POSITION_LIMIT_INCREASE_FEE", + ]) + .optional() + .describe("Income type"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 100; max 1000"), + }, + }, + async ({ symbol, incomeType, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (incomeType) params.incomeType = incomeType; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.income(params); - const data = await futuresClient.income(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} USD-M Futures income records. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} USD-M Futures income records. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures income: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures income: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/index.ts b/src/tools/binance-futures-usdm/index.ts index 749790f4..555d9a71 100644 --- a/src/tools/binance-futures-usdm/index.ts +++ b/src/tools/binance-futures-usdm/index.ts @@ -1,96 +1,98 @@ // src/tools/binance-futures-usdm/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; - -// Market Data -import { registerBinanceFuturesUSDMPing } from "./ping.js"; -import { registerBinanceFuturesUSDMTime } from "./time.js"; -import { registerBinanceFuturesUSDMExchangeInfo } from "./exchangeInfo.js"; -import { registerBinanceFuturesUSDMDepth } from "./depth.js"; -import { registerBinanceFuturesUSDMTrades } from "./trades.js"; -import { registerBinanceFuturesUSDMHistoricalTrades } from "./historicalTrades.js"; -import { registerBinanceFuturesUSDMAggTrades } from "./aggTrades.js"; -import { registerBinanceFuturesUSDMKlines } from "./klines.js"; -import { registerBinanceFuturesUSDMContinuousKlines } from "./continuousKlines.js"; -import { registerBinanceFuturesUSDMIndexPriceKlines } from "./indexPriceKlines.js"; -import { registerBinanceFuturesUSDMMarkPriceKlines } from "./markPriceKlines.js"; -import { registerBinanceFuturesUSDMPremiumIndex } from "./premiumIndex.js"; -import { registerBinanceFuturesUSDMFundingRate } from "./fundingRate.js"; -import { registerBinanceFuturesUSDMTicker24hr } from "./ticker24hr.js"; -import { registerBinanceFuturesUSDMTickerPrice } from "./tickerPrice.js"; -import { registerBinanceFuturesUSDMBookTicker } from "./bookTicker.js"; -import { registerBinanceFuturesUSDMOpenInterest } from "./openInterest.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; // Account & Trading import { registerBinanceFuturesUSDMAccount } from "./account.js"; +import { registerBinanceFuturesUSDMADLQuantile } from "./adlQuantile.js"; +import { registerBinanceFuturesUSDMAggTrades } from "./aggTrades.js"; +import { registerBinanceFuturesUSDMAllOrders } from "./allOrders.js"; import { registerBinanceFuturesUSDMBalance } from "./balance.js"; -import { registerBinanceFuturesUSDMPositionRisk } from "./positionRisk.js"; -import { registerBinanceFuturesUSDMNewOrder } from "./newOrder.js"; import { registerBinanceFuturesUSDMBatchOrders } from "./batchOrders.js"; -import { registerBinanceFuturesUSDMGetOrder } from "./getOrder.js"; -import { registerBinanceFuturesUSDMCancelOrder } from "./cancelOrder.js"; +import { registerBinanceFuturesUSDMBookTicker } from "./bookTicker.js"; import { registerBinanceFuturesUSDMCancelAllOrders } from "./cancelAllOrders.js"; import { registerBinanceFuturesUSDMCancelBatchOrders } from "./cancelBatchOrders.js"; -import { registerBinanceFuturesUSDMOpenOrders } from "./openOrders.js"; -import { registerBinanceFuturesUSDMAllOrders } from "./allOrders.js"; -import { registerBinanceFuturesUSDMUserTrades } from "./userTrades.js"; +import { registerBinanceFuturesUSDMCancelOrder } from "./cancelOrder.js"; +import { registerBinanceFuturesUSDMCommissionRate } from "./commissionRate.js"; +import { registerBinanceFuturesUSDMContinuousKlines } from "./continuousKlines.js"; +import { registerBinanceFuturesUSDMDepth } from "./depth.js"; +import { registerBinanceFuturesUSDMExchangeInfo } from "./exchangeInfo.js"; +import { registerBinanceFuturesUSDMForceOrders } from "./forceOrders.js"; +import { registerBinanceFuturesUSDMFundingRate } from "./fundingRate.js"; +import { registerBinanceFuturesUSDMGetOrder } from "./getOrder.js"; +import { registerBinanceFuturesUSDMHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceFuturesUSDMIncome } from "./income.js"; +import { registerBinanceFuturesUSDMIndexPriceKlines } from "./indexPriceKlines.js"; +import { registerBinanceFuturesUSDMKlines } from "./klines.js"; import { registerBinanceFuturesUSDMLeverage } from "./leverage.js"; +// User Data Stream +import { + registerBinanceFuturesUSDMListenKeyClose, + registerBinanceFuturesUSDMListenKeyCreate, + registerBinanceFuturesUSDMListenKeyRenew, +} from "./listenKey.js"; import { registerBinanceFuturesUSDMMarginType } from "./marginType.js"; +import { registerBinanceFuturesUSDMMarkPriceKlines } from "./markPriceKlines.js"; +import { registerBinanceFuturesUSDMMultiAssetsMode } from "./multiAssetsMode.js"; +import { registerBinanceFuturesUSDMNewOrder } from "./newOrder.js"; +import { registerBinanceFuturesUSDMOpenInterest } from "./openInterest.js"; +import { registerBinanceFuturesUSDMOpenOrders } from "./openOrders.js"; +// Market Data +import { registerBinanceFuturesUSDMPing } from "./ping.js"; import { registerBinanceFuturesUSDMPositionMargin } from "./positionMargin.js"; import { registerBinanceFuturesUSDMPositionMode } from "./positionMode.js"; -import { registerBinanceFuturesUSDMMultiAssetsMode } from "./multiAssetsMode.js"; -import { registerBinanceFuturesUSDMCommissionRate } from "./commissionRate.js"; -import { registerBinanceFuturesUSDMForceOrders } from "./forceOrders.js"; -import { registerBinanceFuturesUSDMADLQuantile } from "./adlQuantile.js"; - -// User Data Stream -import { registerBinanceFuturesUSDMListenKeyCreate, registerBinanceFuturesUSDMListenKeyRenew, registerBinanceFuturesUSDMListenKeyClose } from "./listenKey.js"; +import { registerBinanceFuturesUSDMPositionRisk } from "./positionRisk.js"; +import { registerBinanceFuturesUSDMPremiumIndex } from "./premiumIndex.js"; +import { registerBinanceFuturesUSDMTicker24hr } from "./ticker24hr.js"; +import { registerBinanceFuturesUSDMTickerPrice } from "./tickerPrice.js"; +import { registerBinanceFuturesUSDMTime } from "./time.js"; +import { registerBinanceFuturesUSDMTrades } from "./trades.js"; +import { registerBinanceFuturesUSDMUserTrades } from "./userTrades.js"; export function registerBinanceFuturesUSDMTools(server: McpServer) { - // Market Data - registerBinanceFuturesUSDMPing(server); - registerBinanceFuturesUSDMTime(server); - registerBinanceFuturesUSDMExchangeInfo(server); - registerBinanceFuturesUSDMDepth(server); - registerBinanceFuturesUSDMTrades(server); - registerBinanceFuturesUSDMHistoricalTrades(server); - registerBinanceFuturesUSDMAggTrades(server); - registerBinanceFuturesUSDMKlines(server); - registerBinanceFuturesUSDMContinuousKlines(server); - registerBinanceFuturesUSDMIndexPriceKlines(server); - registerBinanceFuturesUSDMMarkPriceKlines(server); - registerBinanceFuturesUSDMPremiumIndex(server); - registerBinanceFuturesUSDMFundingRate(server); - registerBinanceFuturesUSDMTicker24hr(server); - registerBinanceFuturesUSDMTickerPrice(server); - registerBinanceFuturesUSDMBookTicker(server); - registerBinanceFuturesUSDMOpenInterest(server); + // Market Data + registerBinanceFuturesUSDMPing(server); + registerBinanceFuturesUSDMTime(server); + registerBinanceFuturesUSDMExchangeInfo(server); + registerBinanceFuturesUSDMDepth(server); + registerBinanceFuturesUSDMTrades(server); + registerBinanceFuturesUSDMHistoricalTrades(server); + registerBinanceFuturesUSDMAggTrades(server); + registerBinanceFuturesUSDMKlines(server); + registerBinanceFuturesUSDMContinuousKlines(server); + registerBinanceFuturesUSDMIndexPriceKlines(server); + registerBinanceFuturesUSDMMarkPriceKlines(server); + registerBinanceFuturesUSDMPremiumIndex(server); + registerBinanceFuturesUSDMFundingRate(server); + registerBinanceFuturesUSDMTicker24hr(server); + registerBinanceFuturesUSDMTickerPrice(server); + registerBinanceFuturesUSDMBookTicker(server); + registerBinanceFuturesUSDMOpenInterest(server); - // Account & Trading - registerBinanceFuturesUSDMAccount(server); - registerBinanceFuturesUSDMBalance(server); - registerBinanceFuturesUSDMPositionRisk(server); - registerBinanceFuturesUSDMNewOrder(server); - registerBinanceFuturesUSDMBatchOrders(server); - registerBinanceFuturesUSDMGetOrder(server); - registerBinanceFuturesUSDMCancelOrder(server); - registerBinanceFuturesUSDMCancelAllOrders(server); - registerBinanceFuturesUSDMCancelBatchOrders(server); - registerBinanceFuturesUSDMOpenOrders(server); - registerBinanceFuturesUSDMAllOrders(server); - registerBinanceFuturesUSDMUserTrades(server); - registerBinanceFuturesUSDMIncome(server); - registerBinanceFuturesUSDMLeverage(server); - registerBinanceFuturesUSDMMarginType(server); - registerBinanceFuturesUSDMPositionMargin(server); - registerBinanceFuturesUSDMPositionMode(server); - registerBinanceFuturesUSDMMultiAssetsMode(server); - registerBinanceFuturesUSDMCommissionRate(server); - registerBinanceFuturesUSDMForceOrders(server); - registerBinanceFuturesUSDMADLQuantile(server); + // Account & Trading + registerBinanceFuturesUSDMAccount(server); + registerBinanceFuturesUSDMBalance(server); + registerBinanceFuturesUSDMPositionRisk(server); + registerBinanceFuturesUSDMNewOrder(server); + registerBinanceFuturesUSDMBatchOrders(server); + registerBinanceFuturesUSDMGetOrder(server); + registerBinanceFuturesUSDMCancelOrder(server); + registerBinanceFuturesUSDMCancelAllOrders(server); + registerBinanceFuturesUSDMCancelBatchOrders(server); + registerBinanceFuturesUSDMOpenOrders(server); + registerBinanceFuturesUSDMAllOrders(server); + registerBinanceFuturesUSDMUserTrades(server); + registerBinanceFuturesUSDMIncome(server); + registerBinanceFuturesUSDMLeverage(server); + registerBinanceFuturesUSDMMarginType(server); + registerBinanceFuturesUSDMPositionMargin(server); + registerBinanceFuturesUSDMPositionMode(server); + registerBinanceFuturesUSDMMultiAssetsMode(server); + registerBinanceFuturesUSDMCommissionRate(server); + registerBinanceFuturesUSDMForceOrders(server); + registerBinanceFuturesUSDMADLQuantile(server); - // User Data Stream - registerBinanceFuturesUSDMListenKeyCreate(server); - registerBinanceFuturesUSDMListenKeyRenew(server); - registerBinanceFuturesUSDMListenKeyClose(server); + // User Data Stream + registerBinanceFuturesUSDMListenKeyCreate(server); + registerBinanceFuturesUSDMListenKeyRenew(server); + registerBinanceFuturesUSDMListenKeyClose(server); } diff --git a/src/tools/binance-futures-usdm/indexPriceKlines.ts b/src/tools/binance-futures-usdm/indexPriceKlines.ts index 3a272f32..1e9dafa9 100644 --- a/src/tools/binance-futures-usdm/indexPriceKlines.ts +++ b/src/tools/binance-futures-usdm/indexPriceKlines.ts @@ -1,47 +1,71 @@ // src/tools/binance-futures-usdm/indexPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMIndexPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesUSDMIndexPriceKlines", - "Get index price Kline/candlestick data for USD-M Futures.", - { - pair: z.string().describe("Trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ pair, interval, startTime, endTime, limit }) => { - try { - const params: any = { pair, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMIndexPriceKlines", + { + description: "Get index price Kline/candlestick data for USD-M Futures.", + inputSchema: { + pair: z.string().describe("Trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ pair, interval, startTime, endTime, limit }) => { + try { + const params: any = { pair, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.indexPriceKlines(params); - const data = await futuresClient.indexPriceKlines(params); + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} index price klines for USD-M Futures ${pair} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} index price klines for USD-M Futures ${pair} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures index price klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures index price klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/klines.ts b/src/tools/binance-futures-usdm/klines.ts index 6b997b0c..5e0c7680 100644 --- a/src/tools/binance-futures-usdm/klines.ts +++ b/src/tools/binance-futures-usdm/klines.ts @@ -1,48 +1,68 @@ // src/tools/binance-futures-usdm/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMKlines(server: McpServer) { - server.tool( - "BinanceFuturesUSDMKlines", - "Get Kline/candlestick bars for a specific USD-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMKlines", + { + description: "Get Kline/candlestick bars for a specific USD-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.klines(params); - const data = await futuresClient.klines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} klines for USD-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} klines for USD-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures klines: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/leverage.ts b/src/tools/binance-futures-usdm/leverage.ts index f3909099..e5443ccb 100644 --- a/src/tools/binance-futures-usdm/leverage.ts +++ b/src/tools/binance-futures-usdm/leverage.ts @@ -1,38 +1,42 @@ // src/tools/binance-futures-usdm/leverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMLeverage(server: McpServer) { - server.tool( - "BinanceFuturesUSDMLeverage", - "Change initial leverage for a symbol in USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - leverage: z.number().describe("Target leverage (1-125)") - }, - async ({ symbol, leverage }) => { - try { - const data = await futuresClient.leverage({ symbol, leverage }); - + server.registerTool( + "BinanceFuturesUSDMLeverage", + { + description: "Change initial leverage for a symbol in USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + leverage: z.number().describe("Target leverage (1-125)"), + }, + }, + async ({ symbol, leverage }) => { + try { + const data = await futuresClient.leverage({ symbol, leverage }); + + return { + content: [ + { + type: "text", + text: `USD-M Futures leverage changed to ${leverage}x for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures leverage changed to ${leverage}x for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change USD-M Futures leverage: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to change USD-M Futures leverage: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/listenKey.ts b/src/tools/binance-futures-usdm/listenKey.ts index 8cbbd923..0e1cf8ee 100644 --- a/src/tools/binance-futures-usdm/listenKey.ts +++ b/src/tools/binance-futures-usdm/listenKey.ts @@ -1,97 +1,97 @@ // src/tools/binance-futures-usdm/listenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMListenKeyCreate(server: McpServer) { - server.tool( - "BinanceFuturesUSDMListenKeyCreate", + server.registerTool( + "BinanceFuturesUSDMListenKeyCreate", + { + description: "Start a new user data stream for USD-M Futures. Returns a listenKey for WebSocket connection.", - {}, - async () => { - try { - const data = await futuresClient.createListenKey(); - + }, + async () => { + try { + const data = await futuresClient.createListenKey(); + + return { + content: [ + { + type: "text", + text: `USD-M Futures listen key created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures listen key created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create USD-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create USD-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } export function registerBinanceFuturesUSDMListenKeyRenew(server: McpServer) { - server.tool( - "BinanceFuturesUSDMListenKeyRenew", - "Keepalive a user data stream to prevent timeout for USD-M Futures.", - {}, - async () => { - try { - const data = await futuresClient.keepAliveListenKey(); - + server.registerTool( + "BinanceFuturesUSDMListenKeyRenew", + { description: "Keepalive a user data stream to prevent timeout for USD-M Futures." }, + async () => { + try { + const data = await futuresClient.keepAliveListenKey(); - return { - content: [ - { - type: "text", - text: `USD-M Futures listen key renewed. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to renew USD-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `USD-M Futures listen key renewed. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to renew USD-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } export function registerBinanceFuturesUSDMListenKeyClose(server: McpServer) { - server.tool( - "BinanceFuturesUSDMListenKeyClose", - "Close a user data stream for USD-M Futures.", - {}, - async () => { - try { - const data = await futuresClient.closeListenKey(); - + server.registerTool( + "BinanceFuturesUSDMListenKeyClose", + { description: "Close a user data stream for USD-M Futures." }, + async () => { + try { + const data = await futuresClient.closeListenKey(); + + return { + content: [ + { + type: "text", + text: `USD-M Futures listen key closed. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures listen key closed. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to close USD-M Futures listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to close USD-M Futures listen key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/marginType.ts b/src/tools/binance-futures-usdm/marginType.ts index b5a58ed3..c3f134c8 100644 --- a/src/tools/binance-futures-usdm/marginType.ts +++ b/src/tools/binance-futures-usdm/marginType.ts @@ -1,38 +1,42 @@ // src/tools/binance-futures-usdm/marginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMMarginType(server: McpServer) { - server.tool( - "BinanceFuturesUSDMMarginType", - "Change margin type for a symbol in USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED") - }, - async ({ symbol, marginType }) => { - try { - const data = await futuresClient.marginType({ symbol, marginType }); - + server.registerTool( + "BinanceFuturesUSDMMarginType", + { + description: "Change margin type for a symbol in USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + marginType: z.enum(["ISOLATED", "CROSSED"]).describe("Margin type: ISOLATED or CROSSED"), + }, + }, + async ({ symbol, marginType }) => { + try { + const data = await futuresClient.marginType({ symbol, marginType }); + + return { + content: [ + { + type: "text", + text: `USD-M Futures margin type changed to ${marginType} for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures margin type changed to ${marginType} for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change USD-M Futures margin type: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to change USD-M Futures margin type: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/markPriceKlines.ts b/src/tools/binance-futures-usdm/markPriceKlines.ts index 6ad0e22a..93da02b3 100644 --- a/src/tools/binance-futures-usdm/markPriceKlines.ts +++ b/src/tools/binance-futures-usdm/markPriceKlines.ts @@ -1,48 +1,71 @@ // src/tools/binance-futures-usdm/markPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMMarkPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesUSDMMarkPriceKlines", - "Get mark price Kline/candlestick data for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1500") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMMarkPriceKlines", + { + description: "Get mark price Kline/candlestick data for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1500"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.markPriceKlines(params); - const data = await futuresClient.markPriceKlines(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} mark price klines for USD-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} mark price klines for USD-M Futures ${symbol} with ${interval} interval. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures mark price klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures mark price klines: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/aggTrades.ts b/src/tools/binance-futures-usdm/market-api/aggTrades.ts index c8e772d4..13acacab 100644 --- a/src/tools/binance-futures-usdm/market-api/aggTrades.ts +++ b/src/tools/binance-futures-usdm/market-api/aggTrades.ts @@ -5,44 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesAggTrades(server: McpServer) { - server.tool( - "BinanceFuturesAggTrades", - "Get compressed aggregate trades for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of trades. Default 500, max 1000") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.aggTrades({ - symbol: params.symbol, - ...(params.fromId !== undefined && { fromId: params.fromId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Aggregate Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get aggregate trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesAggTrades", + { + description: "Get compressed aggregate trades for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of trades. Default 500, max 1000"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.aggTrades({ + symbol: params.symbol, + ...(params.fromId !== undefined && { fromId: params.fromId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Aggregate Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get aggregate trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/assetIndex.ts b/src/tools/binance-futures-usdm/market-api/assetIndex.ts index ae4af796..0cac1013 100644 --- a/src/tools/binance-futures-usdm/market-api/assetIndex.ts +++ b/src/tools/binance-futures-usdm/market-api/assetIndex.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/assetIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesAssetIndex(server: McpServer) { - server.tool( - "BinanceFuturesAssetIndex", - "Get asset index for Multi-Asset margin mode.", - { - symbol: z.string().optional().describe("Symbol (e.g., BTCUSD)") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.assetIndex({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Asset index${params.symbol ? ` for ${params.symbol}` : ''}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get asset index: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesAssetIndex", + { + description: "Get asset index for Multi-Asset margin mode.", + inputSchema: { + symbol: z.string().optional().describe("Symbol (e.g., BTCUSD)"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.assetIndex({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Asset index${params.symbol ? ` for ${params.symbol}` : ""}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get asset index: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/continuousKlines.ts b/src/tools/binance-futures-usdm/market-api/continuousKlines.ts index 4bd3ce07..dab1ba41 100644 --- a/src/tools/binance-futures-usdm/market-api/continuousKlines.ts +++ b/src/tools/binance-futures-usdm/market-api/continuousKlines.ts @@ -5,51 +5,74 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/continuousKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesContinuousKlines(server: McpServer) { - server.tool( - "BinanceFuturesContinuousKlines", - "Get continuous contract kline data for USD-M Futures.", - { - pair: z.string().describe("Underlying pair (e.g., BTCUSDT)"), - contractType: z.enum(["PERPETUAL", "CURRENT_MONTH", "NEXT_MONTH", "CURRENT_QUARTER", "NEXT_QUARTER"]) - .describe("Contract type"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.continuousKlines({ - pair: params.pair, - contractType: params.contractType, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Continuous Klines for ${params.pair} ${params.contractType}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get continuous klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesContinuousKlines", + { + description: "Get continuous contract kline data for USD-M Futures.", + inputSchema: { + pair: z.string().describe("Underlying pair (e.g., BTCUSDT)"), + contractType: z + .enum(["PERPETUAL", "CURRENT_MONTH", "NEXT_MONTH", "CURRENT_QUARTER", "NEXT_QUARTER"]) + .describe("Contract type"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.continuousKlines({ + pair: params.pair, + contractType: params.contractType, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Continuous Klines for ${params.pair} ${params.contractType}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get continuous klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/depth.ts b/src/tools/binance-futures-usdm/market-api/depth.ts index f2ecd2f0..6639aec2 100644 --- a/src/tools/binance-futures-usdm/market-api/depth.ts +++ b/src/tools/binance-futures-usdm/market-api/depth.ts @@ -5,38 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesDepth(server: McpServer) { - server.tool( - "BinanceFuturesDepth", - "Get order book depth data for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - limit: z.number().int().optional().describe("Depth limit: 5, 10, 20, 50, 100, 500, 1000. Default 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.depth({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures Order Book for ${params.symbol}: Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get depth: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesDepth", + { + description: "Get order book depth data for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + limit: z + .number() + .int() + .optional() + .describe("Depth limit: 5, 10, 20, 50, 100, 500, 1000. Default 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.depth({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures Order Book for ${params.symbol}: Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get depth: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/exchangeInfo.ts b/src/tools/binance-futures-usdm/market-api/exchangeInfo.ts index 01174b22..e664441a 100644 --- a/src/tools/binance-futures-usdm/market-api/exchangeInfo.ts +++ b/src/tools/binance-futures-usdm/market-api/exchangeInfo.ts @@ -5,31 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesExchangeInfo(server: McpServer) { - server.tool( - "BinanceFuturesExchangeInfo", - "Get current USD-M Futures exchange trading rules and symbol information.", - {}, - async () => { - try { - const response = await futuresClient.restAPI.exchangeInfo(); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures Exchange Info: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get exchange info: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesExchangeInfo", + { description: "Get current USD-M Futures exchange trading rules and symbol information." }, + async () => { + try { + const response = await futuresClient.restAPI.exchangeInfo(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures Exchange Info: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get exchange info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/fundingInfo.ts b/src/tools/binance-futures-usdm/market-api/fundingInfo.ts index c5faed0f..e03d9106 100644 --- a/src/tools/binance-futures-usdm/market-api/fundingInfo.ts +++ b/src/tools/binance-futures-usdm/market-api/fundingInfo.ts @@ -5,31 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/fundingInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesFundingInfo(server: McpServer) { - server.tool( - "BinanceFuturesFundingInfo", - "Get funding rate info for all perpetual symbols on USD-M Futures.", - {}, - async () => { - try { - const response = await futuresClient.restAPI.fundingInfo(); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Funding Info: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get funding info: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesFundingInfo", + { description: "Get funding rate info for all perpetual symbols on USD-M Futures." }, + async () => { + try { + const response = await futuresClient.restAPI.fundingInfo(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Funding Info: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get funding info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/fundingRate.ts b/src/tools/binance-futures-usdm/market-api/fundingRate.ts index f063dafa..0d19e521 100644 --- a/src/tools/binance-futures-usdm/market-api/fundingRate.ts +++ b/src/tools/binance-futures-usdm/market-api/fundingRate.ts @@ -5,42 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/fundingRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesFundingRate(server: McpServer) { - server.tool( - "BinanceFuturesFundingRate", - "Get funding rate history for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of results. Default 100, max 1000") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.fundingRate({ - symbol: params.symbol, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Funding Rate History for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get funding rate: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesFundingRate", + { + description: "Get funding rate history for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of results. Default 100, max 1000"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.fundingRate({ + symbol: params.symbol, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Funding Rate History for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get funding rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/globalLongShortAccountRatio.ts b/src/tools/binance-futures-usdm/market-api/globalLongShortAccountRatio.ts index 333c9836..b99d78ce 100644 --- a/src/tools/binance-futures-usdm/market-api/globalLongShortAccountRatio.ts +++ b/src/tools/binance-futures-usdm/market-api/globalLongShortAccountRatio.ts @@ -5,44 +5,64 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/globalLongShortAccountRatio.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesGlobalLongShortAccountRatio(server: McpServer) { - server.tool( - "BinanceFuturesGlobalLongShortAccountRatio", - "Get global long/short account ratio for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Data period"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 30, max 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.globalLongShortAccountRatio({ - symbol: params.symbol, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Global long/short account ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get global long/short account ratio: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesGlobalLongShortAccountRatio", + { + description: "Get global long/short account ratio for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Data period"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(500) + .optional() + .describe("Number of records. Default 30, max 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.globalLongShortAccountRatio({ + symbol: params.symbol, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Global long/short account ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to get global long/short account ratio: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/historicalTrades.ts b/src/tools/binance-futures-usdm/market-api/historicalTrades.ts index bde5868d..0955dac1 100644 --- a/src/tools/binance-futures-usdm/market-api/historicalTrades.ts +++ b/src/tools/binance-futures-usdm/market-api/historicalTrades.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesHistoricalTrades(server: McpServer) { - server.tool( - "BinanceFuturesHistoricalTrades", - "Get older trades for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - limit: z.number().int().optional().describe("Number of trades. Default 500, max 1000"), - fromId: z.number().int().optional().describe("Trade ID to start from") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.historicalTrades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }), - ...(params.fromId !== undefined && { fromId: params.fromId }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Historical Futures Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get historical trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesHistoricalTrades", + { + description: "Get older trades for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + limit: z.number().int().optional().describe("Number of trades. Default 500, max 1000"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.historicalTrades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + ...(params.fromId !== undefined && { fromId: params.fromId }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Historical Futures Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get historical trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/index.ts b/src/tools/binance-futures-usdm/market-api/index.ts index cc62faee..00e8ed46 100644 --- a/src/tools/binance-futures-usdm/market-api/index.ts +++ b/src/tools/binance-futures-usdm/market-api/index.ts @@ -5,72 +5,73 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceFuturesPing } from "./ping.js"; -import { registerBinanceFuturesTime } from "./time.js"; -import { registerBinanceFuturesExchangeInfo } from "./exchangeInfo.js"; -import { registerBinanceFuturesDepth } from "./depth.js"; -import { registerBinanceFuturesTrades } from "./trades.js"; -import { registerBinanceFuturesHistoricalTrades } from "./historicalTrades.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFuturesAggTrades } from "./aggTrades.js"; -import { registerBinanceFuturesKlines } from "./klines.js"; +import { registerBinanceFuturesAssetIndex } from "./assetIndex.js"; import { registerBinanceFuturesContinuousKlines } from "./continuousKlines.js"; +import { registerBinanceFuturesDepth } from "./depth.js"; +import { registerBinanceFuturesExchangeInfo } from "./exchangeInfo.js"; +import { registerBinanceFuturesFundingInfo } from "./fundingInfo.js"; +import { registerBinanceFuturesFundingRate } from "./fundingRate.js"; +import { registerBinanceFuturesGlobalLongShortAccountRatio } from "./globalLongShortAccountRatio.js"; +import { registerBinanceFuturesHistoricalTrades } from "./historicalTrades.js"; +import { registerBinanceFuturesIndexInfo } from "./indexInfo.js"; import { registerBinanceFuturesIndexPriceKlines } from "./indexPriceKlines.js"; +import { registerBinanceFuturesKlines } from "./klines.js"; +import { registerBinanceFuturesLvtKlines } from "./lvtKlines.js"; import { registerBinanceFuturesMarkPriceKlines } from "./markPriceKlines.js"; +import { registerBinanceFuturesOpenInterest } from "./openInterest.js"; +import { registerBinanceFuturesOpenInterestHist } from "./openInterestHist.js"; +import { registerBinanceFuturesPing } from "./ping.js"; import { registerBinanceFuturesPremiumIndex } from "./premiumIndex.js"; -import { registerBinanceFuturesFundingRate } from "./fundingRate.js"; -import { registerBinanceFuturesFundingInfo } from "./fundingInfo.js"; +import { registerBinanceFuturesTakerLongShortRatio } from "./takerLongShortRatio.js"; import { registerBinanceFuturesTicker24hr } from "./ticker24hr.js"; -import { registerBinanceFuturesTickerPrice } from "./tickerPrice.js"; import { registerBinanceFuturesTickerBookTicker } from "./tickerBookTicker.js"; -import { registerBinanceFuturesOpenInterest } from "./openInterest.js"; -import { registerBinanceFuturesOpenInterestHist } from "./openInterestHist.js"; +import { registerBinanceFuturesTickerPrice } from "./tickerPrice.js"; +import { registerBinanceFuturesTime } from "./time.js"; import { registerBinanceFuturesTopLongShortAccountRatio } from "./topLongShortAccountRatio.js"; import { registerBinanceFuturesTopLongShortPositionRatio } from "./topLongShortPositionRatio.js"; -import { registerBinanceFuturesGlobalLongShortAccountRatio } from "./globalLongShortAccountRatio.js"; -import { registerBinanceFuturesTakerLongShortRatio } from "./takerLongShortRatio.js"; -import { registerBinanceFuturesLvtKlines } from "./lvtKlines.js"; -import { registerBinanceFuturesIndexInfo } from "./indexInfo.js"; -import { registerBinanceFuturesAssetIndex } from "./assetIndex.js"; +import { registerBinanceFuturesTrades } from "./trades.js"; export function registerBinanceFuturesMarketApiTools(server: McpServer) { - // General - registerBinanceFuturesPing(server); - registerBinanceFuturesTime(server); - registerBinanceFuturesExchangeInfo(server); - - // Market Data - registerBinanceFuturesDepth(server); - registerBinanceFuturesTrades(server); - registerBinanceFuturesHistoricalTrades(server); - registerBinanceFuturesAggTrades(server); - - // Klines - registerBinanceFuturesKlines(server); - registerBinanceFuturesContinuousKlines(server); - registerBinanceFuturesIndexPriceKlines(server); - registerBinanceFuturesMarkPriceKlines(server); - - // Funding & Premium - registerBinanceFuturesPremiumIndex(server); - registerBinanceFuturesFundingRate(server); - registerBinanceFuturesFundingInfo(server); - - // Ticker - registerBinanceFuturesTicker24hr(server); - registerBinanceFuturesTickerPrice(server); - registerBinanceFuturesTickerBookTicker(server); - - // Open Interest & Analytics - registerBinanceFuturesOpenInterest(server); - registerBinanceFuturesOpenInterestHist(server); - registerBinanceFuturesTopLongShortAccountRatio(server); - registerBinanceFuturesTopLongShortPositionRatio(server); - registerBinanceFuturesGlobalLongShortAccountRatio(server); - registerBinanceFuturesTakerLongShortRatio(server); - - // Index - registerBinanceFuturesLvtKlines(server); - registerBinanceFuturesIndexInfo(server); - registerBinanceFuturesAssetIndex(server); + // General + registerBinanceFuturesPing(server); + registerBinanceFuturesTime(server); + registerBinanceFuturesExchangeInfo(server); + + // Market Data + registerBinanceFuturesDepth(server); + registerBinanceFuturesTrades(server); + registerBinanceFuturesHistoricalTrades(server); + registerBinanceFuturesAggTrades(server); + + // Klines + registerBinanceFuturesKlines(server); + registerBinanceFuturesContinuousKlines(server); + registerBinanceFuturesIndexPriceKlines(server); + registerBinanceFuturesMarkPriceKlines(server); + + // Funding & Premium + registerBinanceFuturesPremiumIndex(server); + registerBinanceFuturesFundingRate(server); + registerBinanceFuturesFundingInfo(server); + + // Ticker + registerBinanceFuturesTicker24hr(server); + registerBinanceFuturesTickerPrice(server); + registerBinanceFuturesTickerBookTicker(server); + + // Open Interest & Analytics + registerBinanceFuturesOpenInterest(server); + registerBinanceFuturesOpenInterestHist(server); + registerBinanceFuturesTopLongShortAccountRatio(server); + registerBinanceFuturesTopLongShortPositionRatio(server); + registerBinanceFuturesGlobalLongShortAccountRatio(server); + registerBinanceFuturesTakerLongShortRatio(server); + + // Index + registerBinanceFuturesLvtKlines(server); + registerBinanceFuturesIndexInfo(server); + registerBinanceFuturesAssetIndex(server); } diff --git a/src/tools/binance-futures-usdm/market-api/indexInfo.ts b/src/tools/binance-futures-usdm/market-api/indexInfo.ts index adbc2ee7..72b29a54 100644 --- a/src/tools/binance-futures-usdm/market-api/indexInfo.ts +++ b/src/tools/binance-futures-usdm/market-api/indexInfo.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/indexInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesIndexInfo(server: McpServer) { - server.tool( - "BinanceFuturesIndexInfo", - "Get composite index symbol information for USD-M Futures.", - { - symbol: z.string().optional().describe("Composite index symbol (e.g., DEFIUSDT)") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.indexInfo({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Index info${params.symbol ? ` for ${params.symbol}` : ''}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get index info: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesIndexInfo", + { + description: "Get composite index symbol information for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Composite index symbol (e.g., DEFIUSDT)"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.indexInfo({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index info${params.symbol ? ` for ${params.symbol}` : ""}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get index info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/indexPriceKlines.ts b/src/tools/binance-futures-usdm/market-api/indexPriceKlines.ts index a24ee7eb..9c47bb3a 100644 --- a/src/tools/binance-futures-usdm/market-api/indexPriceKlines.ts +++ b/src/tools/binance-futures-usdm/market-api/indexPriceKlines.ts @@ -5,48 +5,70 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/indexPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesIndexPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesIndexPriceKlines", - "Get index price kline data for USD-M Futures.", - { - pair: z.string().describe("Underlying pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.indexPriceKlines({ - pair: params.pair, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Index Price Klines for ${params.pair}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get index price klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesIndexPriceKlines", + { + description: "Get index price kline data for USD-M Futures.", + inputSchema: { + pair: z.string().describe("Underlying pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.indexPriceKlines({ + pair: params.pair, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Index Price Klines for ${params.pair}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get index price klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/klines.ts b/src/tools/binance-futures-usdm/market-api/klines.ts index c3bdf693..13d88677 100644 --- a/src/tools/binance-futures-usdm/market-api/klines.ts +++ b/src/tools/binance-futures-usdm/market-api/klines.ts @@ -5,48 +5,70 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesKlines(server: McpServer) { - server.tool( - "BinanceFuturesKlines", - "Get kline/candlestick data for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.klines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Klines for ${params.symbol} (${params.interval}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesKlines", + { + description: "Get kline/candlestick data for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.klines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Klines for ${params.symbol} (${params.interval}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/lvtKlines.ts b/src/tools/binance-futures-usdm/market-api/lvtKlines.ts index ecd9648b..9224bbc2 100644 --- a/src/tools/binance-futures-usdm/market-api/lvtKlines.ts +++ b/src/tools/binance-futures-usdm/market-api/lvtKlines.ts @@ -5,48 +5,75 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/lvtKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesLvtKlines(server: McpServer) { - server.tool( - "BinanceFuturesLvtKlines", - "Get historical BLVT NAV Kline/candlestick data.", - { - symbol: z.string().describe("BLVT symbol (e.g., BTCDOWN, BTCUP)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(1000).optional().describe("Number of klines. Default 500, max 1000") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.lvtKlines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `LVT klines for ${params.symbol} (${params.interval}): ${Array.isArray(data) ? data.length : 0} candles. ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get LVT klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesLvtKlines", + { + description: "Get historical BLVT NAV Kline/candlestick data.", + inputSchema: { + symbol: z.string().describe("BLVT symbol (e.g., BTCDOWN, BTCUP)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(1000) + .optional() + .describe("Number of klines. Default 500, max 1000"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.lvtKlines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `LVT klines for ${params.symbol} (${params.interval}): ${Array.isArray(data) ? data.length : 0} candles. ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get LVT klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/markPriceKlines.ts b/src/tools/binance-futures-usdm/market-api/markPriceKlines.ts index cb7af184..8e0dac13 100644 --- a/src/tools/binance-futures-usdm/market-api/markPriceKlines.ts +++ b/src/tools/binance-futures-usdm/market-api/markPriceKlines.ts @@ -5,48 +5,70 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/markPriceKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesMarkPriceKlines(server: McpServer) { - server.tool( - "BinanceFuturesMarkPriceKlines", - "Get mark price kline data for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", - "1h", "2h", "4h", "6h", "8h", "12h", - "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.markPriceKlines({ - symbol: params.symbol, - interval: params.interval, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Mark Price Klines for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get mark price klines: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesMarkPriceKlines", + { + description: "Get mark price kline data for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of klines. Default 500, max 1500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.markPriceKlines({ + symbol: params.symbol, + interval: params.interval, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Mark Price Klines for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get mark price klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/openInterest.ts b/src/tools/binance-futures-usdm/market-api/openInterest.ts index 5487cb41..07b164d3 100644 --- a/src/tools/binance-futures-usdm/market-api/openInterest.ts +++ b/src/tools/binance-futures-usdm/market-api/openInterest.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/openInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesOpenInterest(server: McpServer) { - server.tool( - "BinanceFuturesOpenInterest", - "Get current open interest for USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.openInterest({ - symbol: params.symbol - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Open interest for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get open interest: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesOpenInterest", + { + description: "Get current open interest for USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.openInterest({ + symbol: params.symbol, + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Open interest for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open interest: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/openInterestHist.ts b/src/tools/binance-futures-usdm/market-api/openInterestHist.ts index a93b42ed..2f99d265 100644 --- a/src/tools/binance-futures-usdm/market-api/openInterestHist.ts +++ b/src/tools/binance-futures-usdm/market-api/openInterestHist.ts @@ -5,44 +5,59 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/openInterestHist.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesOpenInterestHist(server: McpServer) { - server.tool( - "BinanceFuturesOpenInterestHist", - "Get historical open interest statistics for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Data period"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 30, max 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.openInterestHist({ - symbol: params.symbol, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Historical open interest for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get open interest history: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesOpenInterestHist", + { + description: "Get historical open interest statistics for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Data period"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(500) + .optional() + .describe("Number of records. Default 30, max 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.openInterestHist({ + symbol: params.symbol, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Historical open interest for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open interest history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/ping.ts b/src/tools/binance-futures-usdm/market-api/ping.ts index 156afc7e..f2d290db 100644 --- a/src/tools/binance-futures-usdm/market-api/ping.ts +++ b/src/tools/binance-futures-usdm/market-api/ping.ts @@ -5,31 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesPing(server: McpServer) { - server.tool( - "BinanceFuturesPing", - "Test connectivity to the USD-M Futures REST API.", - {}, - async () => { - try { - const response = await futuresClient.restAPI.ping(); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures API connection successful: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Futures ping failed: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesPing", + { description: "Test connectivity to the USD-M Futures REST API." }, + async () => { + try { + const response = await futuresClient.restAPI.ping(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures API connection successful: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Futures ping failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/premiumIndex.ts b/src/tools/binance-futures-usdm/market-api/premiumIndex.ts index bfec6054..ce7e52ee 100644 --- a/src/tools/binance-futures-usdm/market-api/premiumIndex.ts +++ b/src/tools/binance-futures-usdm/market-api/premiumIndex.ts @@ -5,36 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/premiumIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesPremiumIndex(server: McpServer) { - server.tool( - "BinanceFuturesPremiumIndex", - "Get mark price and funding rate for USD-M Futures symbols.", - { - symbol: z.string().optional().describe("Futures symbol (e.g., BTCUSDT). If omitted, returns all symbols") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.premiumIndex({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Premium Index: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get premium index: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesPremiumIndex", + { + description: "Get mark price and funding rate for USD-M Futures symbols.", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Futures symbol (e.g., BTCUSDT). If omitted, returns all symbols"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.premiumIndex({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Premium Index: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get premium index: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/takerLongShortRatio.ts b/src/tools/binance-futures-usdm/market-api/takerLongShortRatio.ts index cbbc5139..be6f2fde 100644 --- a/src/tools/binance-futures-usdm/market-api/takerLongShortRatio.ts +++ b/src/tools/binance-futures-usdm/market-api/takerLongShortRatio.ts @@ -5,44 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/takerLongShortRatio.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTakerLongShortRatio(server: McpServer) { - server.tool( - "BinanceFuturesTakerLongShortRatio", - "Get taker long/short ratio (buy/sell volume) for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Data period"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 30, max 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.takerlongshortRatio({ - symbol: params.symbol, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Taker long/short ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get taker long/short ratio: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTakerLongShortRatio", + { + description: "Get taker long/short ratio (buy/sell volume) for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Data period"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(500) + .optional() + .describe("Number of records. Default 30, max 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.takerlongshortRatio({ + symbol: params.symbol, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Taker long/short ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get taker long/short ratio: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/ticker24hr.ts b/src/tools/binance-futures-usdm/market-api/ticker24hr.ts index 518ffa57..58ef192d 100644 --- a/src/tools/binance-futures-usdm/market-api/ticker24hr.ts +++ b/src/tools/binance-futures-usdm/market-api/ticker24hr.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTicker24hr(server: McpServer) { - server.tool( - "BinanceFuturesTicker24hr", - "Get 24 hour rolling window price change statistics for USD-M Futures.", - { - symbol: z.string().optional().describe("Futures symbol. If omitted, returns all symbols") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.ticker24hr({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `24hr Ticker: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get 24hr ticker: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTicker24hr", + { + description: "Get 24 hour rolling window price change statistics for USD-M Futures.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol. If omitted, returns all symbols"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.ticker24hr({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `24hr Ticker: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get 24hr ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/tickerBookTicker.ts b/src/tools/binance-futures-usdm/market-api/tickerBookTicker.ts index 8299dc63..60a8bf9b 100644 --- a/src/tools/binance-futures-usdm/market-api/tickerBookTicker.ts +++ b/src/tools/binance-futures-usdm/market-api/tickerBookTicker.ts @@ -5,36 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/tickerBookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTickerBookTicker(server: McpServer) { - server.tool( - "BinanceFuturesTickerBookTicker", - "Get best price/qty on the order book for USD-M Futures symbol(s).", - { - symbol: z.string().optional().describe("Futures symbol (e.g., BTCUSDT). If not provided, returns all symbols") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.tickerBookTicker({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Book ticker${params.symbol ? ` for ${params.symbol}` : ''}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get book ticker: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTickerBookTicker", + { + description: "Get best price/qty on the order book for USD-M Futures symbol(s).", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Futures symbol (e.g., BTCUSDT). If not provided, returns all symbols"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.tickerBookTicker({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Book ticker${params.symbol ? ` for ${params.symbol}` : ""}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get book ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/tickerPrice.ts b/src/tools/binance-futures-usdm/market-api/tickerPrice.ts index fe03246a..c433c203 100644 --- a/src/tools/binance-futures-usdm/market-api/tickerPrice.ts +++ b/src/tools/binance-futures-usdm/market-api/tickerPrice.ts @@ -5,36 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTickerPrice(server: McpServer) { - server.tool( - "BinanceFuturesTickerPrice", - "Get latest price for a USD-M Futures symbol or all symbols.", - { - symbol: z.string().optional().describe("Futures symbol. If omitted, returns all symbols") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.tickerPrice({ - ...(params.symbol && { symbol: params.symbol }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Price Ticker: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get price ticker: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTickerPrice", + { + description: "Get latest price for a USD-M Futures symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Futures symbol. If omitted, returns all symbols"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.tickerPrice({ + ...(params.symbol && { symbol: params.symbol }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Price Ticker: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get price ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/time.ts b/src/tools/binance-futures-usdm/market-api/time.ts index f17d8748..89de3693 100644 --- a/src/tools/binance-futures-usdm/market-api/time.ts +++ b/src/tools/binance-futures-usdm/market-api/time.ts @@ -5,31 +5,35 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesTime(server: McpServer) { - server.tool( - "BinanceFuturesTime", - "Get current USD-M Futures server time.", - {}, - async () => { - try { - const response = await futuresClient.restAPI.time(); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Futures server time: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get server time: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTime", + { description: "Get current USD-M Futures server time." }, + async () => { + try { + const response = await futuresClient.restAPI.time(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Futures server time: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/topLongShortAccountRatio.ts b/src/tools/binance-futures-usdm/market-api/topLongShortAccountRatio.ts index a13ff67c..a18872f6 100644 --- a/src/tools/binance-futures-usdm/market-api/topLongShortAccountRatio.ts +++ b/src/tools/binance-futures-usdm/market-api/topLongShortAccountRatio.ts @@ -5,44 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/topLongShortAccountRatio.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTopLongShortAccountRatio(server: McpServer) { - server.tool( - "BinanceFuturesTopLongShortAccountRatio", - "Get top trader long/short account ratio for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Data period"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 30, max 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.topLongShortAccountRatio({ - symbol: params.symbol, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Top traders long/short account ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get top long/short account ratio: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTopLongShortAccountRatio", + { + description: "Get top trader long/short account ratio for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Data period"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(500) + .optional() + .describe("Number of records. Default 30, max 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.topLongShortAccountRatio({ + symbol: params.symbol, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Top traders long/short account ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get top long/short account ratio: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/topLongShortPositionRatio.ts b/src/tools/binance-futures-usdm/market-api/topLongShortPositionRatio.ts index aa919141..b6800199 100644 --- a/src/tools/binance-futures-usdm/market-api/topLongShortPositionRatio.ts +++ b/src/tools/binance-futures-usdm/market-api/topLongShortPositionRatio.ts @@ -5,44 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/topLongShortPositionRatio.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTopLongShortPositionRatio(server: McpServer) { - server.tool( - "BinanceFuturesTopLongShortPositionRatio", - "Get top trader long/short position ratio for USD-M Futures.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]).describe("Data period"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(500).optional().describe("Number of records. Default 30, max 500") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.topLongShortPositionRatio({ - symbol: params.symbol, - period: params.period, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Top traders long/short position ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get top long/short position ratio: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTopLongShortPositionRatio", + { + description: "Get top trader long/short position ratio for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + period: z + .enum(["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"]) + .describe("Data period"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(500) + .optional() + .describe("Number of records. Default 30, max 500"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.topLongShortPositionRatio({ + symbol: params.symbol, + period: params.period, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Top traders long/short position ratio for ${params.symbol} (${params.period}): ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get top long/short position ratio: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/market-api/trades.ts b/src/tools/binance-futures-usdm/market-api/trades.ts index 1e88994a..396f1473 100644 --- a/src/tools/binance-futures-usdm/market-api/trades.ts +++ b/src/tools/binance-futures-usdm/market-api/trades.ts @@ -5,38 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/market-api/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesTrades(server: McpServer) { - server.tool( - "BinanceFuturesTrades", - "Get recent trades for a USD-M Futures symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - limit: z.number().int().optional().describe("Number of trades to return. Default 500, max 1000") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.trades({ - symbol: params.symbol, - ...(params.limit && { limit: params.limit }) - }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Recent Futures Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesTrades", + { + description: "Get recent trades for a USD-M Futures symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + limit: z + .number() + .int() + .optional() + .describe("Number of trades to return. Default 500, max 1000"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.trades({ + symbol: params.symbol, + ...(params.limit && { limit: params.limit }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Recent Futures Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/multiAssetsMode.ts b/src/tools/binance-futures-usdm/multiAssetsMode.ts index 1f8251c0..09a2cf33 100644 --- a/src/tools/binance-futures-usdm/multiAssetsMode.ts +++ b/src/tools/binance-futures-usdm/multiAssetsMode.ts @@ -1,37 +1,48 @@ // src/tools/binance-futures-usdm/multiAssetsMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMMultiAssetsMode(server: McpServer) { - server.tool( - "BinanceFuturesUSDMMultiAssetsMode", - "Change multi-assets mode for USD-M Futures.", - { - multiAssetsMargin: z.boolean().describe("true: Enable multi-assets mode, false: Disable multi-assets mode") - }, - async ({ multiAssetsMargin }) => { - try { - const data = await futuresClient.multiAssetsMargin({ multiAssetsMargin: multiAssetsMargin ? "true" : "false" }); - + server.registerTool( + "BinanceFuturesUSDMMultiAssetsMode", + { + description: "Change multi-assets mode for USD-M Futures.", + inputSchema: { + multiAssetsMargin: z + .boolean() + .describe("true: Enable multi-assets mode, false: Disable multi-assets mode"), + }, + }, + async ({ multiAssetsMargin }) => { + try { + const data = await futuresClient.multiAssetsMargin({ + multiAssetsMargin: multiAssetsMargin ? "true" : "false", + }); + + return { + content: [ + { + type: "text", + text: `USD-M Futures multi-assets mode ${multiAssetsMargin ? "enabled" : "disabled"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures multi-assets mode ${multiAssetsMargin ? 'enabled' : 'disabled'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change USD-M Futures multi-assets mode: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to change USD-M Futures multi-assets mode: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/newOrder.ts b/src/tools/binance-futures-usdm/newOrder.ts index 55d84daa..1af05ec1 100644 --- a/src/tools/binance-futures-usdm/newOrder.ts +++ b/src/tools/binance-futures-usdm/newOrder.ts @@ -1,72 +1,105 @@ // src/tools/binance-futures-usdm/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMNewOrder(server: McpServer) { - server.tool( - "BinanceFuturesUSDMNewOrder", - "Create a new order for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"]).describe("Order type"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side. Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), - quantity: z.number().optional().describe("Order quantity"), - reduceOnly: z.boolean().optional().describe("Cannot be sent in Hedge Mode; cannot be sent with closePosition=true"), - price: z.number().optional().describe("Order price"), - newClientOrderId: z.string().optional().describe("Client order ID"), - stopPrice: z.number().optional().describe("Stop price for STOP/STOP_MARKET/TAKE_PROFIT/TAKE_PROFIT_MARKET"), - closePosition: z.boolean().optional().describe("Close all position. Used with STOP_MARKET or TAKE_PROFIT_MARKET"), - activationPrice: z.number().optional().describe("Activation price for TRAILING_STOP_MARKET"), - callbackRate: z.number().optional().describe("Callback rate for TRAILING_STOP_MARKET"), - workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional().describe("StopPrice triggered by MARK_PRICE or CONTRACT_PRICE"), - priceProtect: z.boolean().optional().describe("Price protect"), - newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type") - }, - async (params) => { - try { - const requestParams: any = { - symbol: params.symbol, - side: params.side, - type: params.type - }; + server.registerTool( + "BinanceFuturesUSDMNewOrder", + { + description: "Create a new order for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side. Default BOTH for One-way Mode; LONG or SHORT for Hedge Mode"), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), + quantity: z.number().optional().describe("Order quantity"), + reduceOnly: z + .boolean() + .optional() + .describe("Cannot be sent in Hedge Mode; cannot be sent with closePosition=true"), + price: z.number().optional().describe("Order price"), + newClientOrderId: z.string().optional().describe("Client order ID"), + stopPrice: z + .number() + .optional() + .describe("Stop price for STOP/STOP_MARKET/TAKE_PROFIT/TAKE_PROFIT_MARKET"), + closePosition: z + .boolean() + .optional() + .describe("Close all position. Used with STOP_MARKET or TAKE_PROFIT_MARKET"), + activationPrice: z + .number() + .optional() + .describe("Activation price for TRAILING_STOP_MARKET"), + callbackRate: z.number().optional().describe("Callback rate for TRAILING_STOP_MARKET"), + workingType: z + .enum(["MARK_PRICE", "CONTRACT_PRICE"]) + .optional() + .describe("StopPrice triggered by MARK_PRICE or CONTRACT_PRICE"), + priceProtect: z.boolean().optional().describe("Price protect"), + newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), + }, + }, + async (params) => { + try { + const requestParams: any = { + symbol: params.symbol, + side: params.side, + type: params.type, + }; + + if (params.positionSide) requestParams.positionSide = params.positionSide; + if (params.timeInForce) requestParams.timeInForce = params.timeInForce; + if (params.quantity !== undefined) requestParams.quantity = params.quantity; + if (params.reduceOnly !== undefined) requestParams.reduceOnly = params.reduceOnly; + if (params.price !== undefined) requestParams.price = params.price; + if (params.newClientOrderId) requestParams.newClientOrderId = params.newClientOrderId; + if (params.stopPrice !== undefined) requestParams.stopPrice = params.stopPrice; + if (params.closePosition !== undefined) requestParams.closePosition = params.closePosition; + if (params.activationPrice !== undefined) + requestParams.activationPrice = params.activationPrice; + if (params.callbackRate !== undefined) requestParams.callbackRate = params.callbackRate; + if (params.workingType) requestParams.workingType = params.workingType; + if (params.priceProtect !== undefined) requestParams.priceProtect = params.priceProtect; + if (params.newOrderRespType) requestParams.newOrderRespType = params.newOrderRespType; - if (params.positionSide) requestParams.positionSide = params.positionSide; - if (params.timeInForce) requestParams.timeInForce = params.timeInForce; - if (params.quantity !== undefined) requestParams.quantity = params.quantity; - if (params.reduceOnly !== undefined) requestParams.reduceOnly = params.reduceOnly; - if (params.price !== undefined) requestParams.price = params.price; - if (params.newClientOrderId) requestParams.newClientOrderId = params.newClientOrderId; - if (params.stopPrice !== undefined) requestParams.stopPrice = params.stopPrice; - if (params.closePosition !== undefined) requestParams.closePosition = params.closePosition; - if (params.activationPrice !== undefined) requestParams.activationPrice = params.activationPrice; - if (params.callbackRate !== undefined) requestParams.callbackRate = params.callbackRate; - if (params.workingType) requestParams.workingType = params.workingType; - if (params.priceProtect !== undefined) requestParams.priceProtect = params.priceProtect; - if (params.newOrderRespType) requestParams.newOrderRespType = params.newOrderRespType; + const data = await futuresClient.newOrder(requestParams); - const data = await futuresClient.newOrder(requestParams); - + return { + content: [ + { + type: "text", + text: `USD-M Futures order created successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures order created successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create USD-M Futures order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create USD-M Futures order: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/openInterest.ts b/src/tools/binance-futures-usdm/openInterest.ts index 965a4525..d9e3ec12 100644 --- a/src/tools/binance-futures-usdm/openInterest.ts +++ b/src/tools/binance-futures-usdm/openInterest.ts @@ -1,37 +1,44 @@ // src/tools/binance-futures-usdm/openInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMOpenInterest(server: McpServer) { - server.tool( - "BinanceFuturesUSDMOpenInterest", - "Get present open interest of a specific symbol for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const data = await futuresClient.openInterest({ symbol }); - + server.registerTool( + "BinanceFuturesUSDMOpenInterest", + { + description: "Get present open interest of a specific symbol for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const data = await futuresClient.openInterest({ symbol }); + + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures open interest for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures open interest for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures open interest: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures open interest: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/openOrders.ts b/src/tools/binance-futures-usdm/openOrders.ts index 24a7c882..3c81ad2b 100644 --- a/src/tools/binance-futures-usdm/openOrders.ts +++ b/src/tools/binance-futures-usdm/openOrders.ts @@ -1,40 +1,49 @@ // src/tools/binance-futures-usdm/openOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMOpenOrders(server: McpServer) { - server.tool( - "BinanceFuturesUSDMOpenOrders", - "Get all current open orders for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all open orders") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMOpenOrders", + { + description: "Get all current open orders for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all open orders", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.openOrders(params); - const data = await futuresClient.openOrders(params); - + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures open orders${symbol ? ` for ${symbol}` : ""}. Count: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures open orders${symbol ? ` for ${symbol}` : ''}. Count: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures open orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/ping.ts b/src/tools/binance-futures-usdm/ping.ts index e6d219a5..bc3019da 100644 --- a/src/tools/binance-futures-usdm/ping.ts +++ b/src/tools/binance-futures-usdm/ping.ts @@ -1,33 +1,32 @@ // src/tools/binance-futures-usdm/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMPing(server: McpServer) { - server.tool( - "BinanceFuturesUSDMPing", - "Test connectivity to the USD-M Futures REST API.", - {}, - async () => { - try { - const data = await futuresClient.ping(); - - return { - content: [ - { - type: "text", - text: `USD-M Futures API connectivity test successful. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to ping USD-M Futures API: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesUSDMPing", + { description: "Test connectivity to the USD-M Futures REST API." }, + async () => { + try { + const data = await futuresClient.ping(); + + return { + content: [ + { + type: "text", + text: `USD-M Futures API connectivity test successful. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to ping USD-M Futures API: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/positionMargin.ts b/src/tools/binance-futures-usdm/positionMargin.ts index 264aae9a..a63232cb 100644 --- a/src/tools/binance-futures-usdm/positionMargin.ts +++ b/src/tools/binance-futures-usdm/positionMargin.ts @@ -1,43 +1,53 @@ // src/tools/binance-futures-usdm/positionMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMPositionMargin(server: McpServer) { - server.tool( - "BinanceFuturesUSDMPositionMargin", - "Modify isolated position margin for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side. Default BOTH for One-way Mode"), - amount: z.number().describe("Amount to add or remove"), - type: z.number().describe("1: Add margin, 2: Remove margin") - }, - async ({ symbol, positionSide, amount, type }) => { - try { - const params: any = { symbol, amount, type }; - if (positionSide) params.positionSide = positionSide; + server.registerTool( + "BinanceFuturesUSDMPositionMargin", + { + description: "Modify isolated position margin for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side. Default BOTH for One-way Mode"), + amount: z.number().describe("Amount to add or remove"), + type: z.number().describe("1: Add margin, 2: Remove margin"), + }, + }, + async ({ symbol, positionSide, amount, type }) => { + try { + const params: any = { symbol, amount, type }; + if (positionSide) params.positionSide = positionSide; + + const data = await futuresClient.positionMargin(params); - const data = await futuresClient.positionMargin(params); - + return { + content: [ + { + type: "text", + text: `USD-M Futures position margin modified for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures position margin modified for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to modify USD-M Futures position margin: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to modify USD-M Futures position margin: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/positionMode.ts b/src/tools/binance-futures-usdm/positionMode.ts index 9c11c6ae..f12b8dc5 100644 --- a/src/tools/binance-futures-usdm/positionMode.ts +++ b/src/tools/binance-futures-usdm/positionMode.ts @@ -1,37 +1,43 @@ // src/tools/binance-futures-usdm/positionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMPositionMode(server: McpServer) { - server.tool( - "BinanceFuturesUSDMPositionMode", - "Change position mode for USD-M Futures (One-way or Hedge Mode).", - { - dualSidePosition: z.boolean().describe("true: Hedge Mode, false: One-way Mode") - }, - async ({ dualSidePosition }) => { - try { - const data = await futuresClient.changePositionMode({ dualSidePosition: dualSidePosition ? "true" : "false" }); - + server.registerTool( + "BinanceFuturesUSDMPositionMode", + { + description: "Change position mode for USD-M Futures (One-way or Hedge Mode).", + inputSchema: { + dualSidePosition: z.boolean().describe("true: Hedge Mode, false: One-way Mode"), + }, + }, + async ({ dualSidePosition }) => { + try { + const data = await futuresClient.changePositionMode({ + dualSidePosition: dualSidePosition ? "true" : "false", + }); + + return { + content: [ + { + type: "text", + text: `USD-M Futures position mode changed to ${dualSidePosition ? "Hedge Mode" : "One-way Mode"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `USD-M Futures position mode changed to ${dualSidePosition ? 'Hedge Mode' : 'One-way Mode'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change USD-M Futures position mode: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to change USD-M Futures position mode: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/positionRisk.ts b/src/tools/binance-futures-usdm/positionRisk.ts index 2bede2e2..631bea23 100644 --- a/src/tools/binance-futures-usdm/positionRisk.ts +++ b/src/tools/binance-futures-usdm/positionRisk.ts @@ -1,40 +1,52 @@ // src/tools/binance-futures-usdm/positionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMPositionRisk(server: McpServer) { - server.tool( - "BinanceFuturesUSDMPositionRisk", - "Get current position information for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all positions") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMPositionRisk", + { + description: "Get current position information for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all positions", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.positionRisk(params); - const data = await futuresClient.positionRisk(params); - + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures position risk${symbol ? ` for ${symbol}` : " for all positions"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures position risk${symbol ? ` for ${symbol}` : ' for all positions'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures position risk: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures position risk: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/premiumIndex.ts b/src/tools/binance-futures-usdm/premiumIndex.ts index 4cf1631f..3ca4143d 100644 --- a/src/tools/binance-futures-usdm/premiumIndex.ts +++ b/src/tools/binance-futures-usdm/premiumIndex.ts @@ -1,40 +1,52 @@ // src/tools/binance-futures-usdm/premiumIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMPremiumIndex(server: McpServer) { - server.tool( - "BinanceFuturesUSDMPremiumIndex", - "Get mark price and funding rate for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMPremiumIndex", + { + description: "Get mark price and funding rate for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.premiumIndex(params); - const data = await futuresClient.premiumIndex(params); - + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures premium index${symbol ? ` for ${symbol}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures premium index${symbol ? ` for ${symbol}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures premium index: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures premium index: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/ticker24hr.ts b/src/tools/binance-futures-usdm/ticker24hr.ts index c62f104f..81816689 100644 --- a/src/tools/binance-futures-usdm/ticker24hr.ts +++ b/src/tools/binance-futures-usdm/ticker24hr.ts @@ -1,40 +1,49 @@ // src/tools/binance-futures-usdm/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMTicker24hr(server: McpServer) { - server.tool( - "BinanceFuturesUSDMTicker24hr", - "Get 24-hour rolling window price change statistics for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMTicker24hr", + { + description: "Get 24-hour rolling window price change statistics for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.ticker24hr(params); - const data = await futuresClient.ticker24hr(params); - + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures 24hr ticker${symbol ? ` for ${symbol}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures 24hr ticker${symbol ? ` for ${symbol}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures 24hr ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures 24hr ticker: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/tickerPrice.ts b/src/tools/binance-futures-usdm/tickerPrice.ts index d7b9e040..66e3e1a0 100644 --- a/src/tools/binance-futures-usdm/tickerPrice.ts +++ b/src/tools/binance-futures-usdm/tickerPrice.ts @@ -1,40 +1,52 @@ // src/tools/binance-futures-usdm/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMTickerPrice(server: McpServer) { - server.tool( - "BinanceFuturesUSDMTickerPrice", - "Get latest price for a symbol or symbols for USD-M Futures.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; + server.registerTool( + "BinanceFuturesUSDMTickerPrice", + { + description: "Get latest price for a symbol or symbols for USD-M Futures.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Symbol of the trading pair (e.g., BTCUSDT). If not provided, returns all symbols", + ), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await futuresClient.tickerPrice(params); - const data = await futuresClient.tickerPrice(params); - + return { + content: [ + { + type: "text", + text: `Retrieved USD-M Futures ticker price${symbol ? ` for ${symbol}` : " for all symbols"}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved USD-M Futures ticker price${symbol ? ` for ${symbol}` : ' for all symbols'}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures ticker price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures ticker price: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/time.ts b/src/tools/binance-futures-usdm/time.ts index 1e5290e5..6c38ecd4 100644 --- a/src/tools/binance-futures-usdm/time.ts +++ b/src/tools/binance-futures-usdm/time.ts @@ -1,33 +1,34 @@ // src/tools/binance-futures-usdm/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMTime(server: McpServer) { - server.tool( - "BinanceFuturesUSDMTime", - "Get the current server time from the USD-M Futures API.", - {}, - async () => { - try { - const data = await futuresClient.time(); - - return { - content: [ - { - type: "text", - text: `USD-M Futures server time: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get USD-M Futures server time: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesUSDMTime", + { description: "Get the current server time from the USD-M Futures API." }, + async () => { + try { + const data = await futuresClient.time(); + + return { + content: [ + { + type: "text", + text: `USD-M Futures server time: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get USD-M Futures server time: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/allOrders.ts b/src/tools/binance-futures-usdm/trade-api/allOrders.ts index b9e91723..9dc2fe97 100644 --- a/src/tools/binance-futures-usdm/trade-api/allOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/allOrders.ts @@ -5,53 +5,57 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesAllOrders", + server.registerTool( + "BinanceFuturesAllOrders", + { + description: "Get all account orders (active, canceled, or filled) for a symbol. Returns orders from the last 7 days by default.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("If set, return orders >= this orderId"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of results (default 500, max 1000)") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.allOrders( - params.symbol, - { - orderId: params.orderId, - startTime: params.startTime, - endTime: params.endTime, - limit: params.limit - } - ); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("If set, return orders >= this orderId"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of results (default 500, max 1000)"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.allOrders({ + symbol: params.symbol, + orderId: params.orderId, + startTime: params.startTime, + endTime: params.endTime, + limit: params.limit, + }); + + return { + content: [ + { + type: "text" as const, + text: JSON.stringify(response.data, null, 2), + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: JSON.stringify(response.data, null, 2) - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: `Error getting all orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text" as const, + text: `Error getting all orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/batchOrders.ts b/src/tools/binance-futures-usdm/trade-api/batchOrders.ts index f851d2c0..ab2fda1c 100644 --- a/src/tools/binance-futures-usdm/trade-api/batchOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/batchOrders.ts @@ -5,69 +5,93 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + const orderSchema = z.object({ - symbol: z.string(), - side: z.enum(["BUY", "SELL"]), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional(), - type: z.enum([ - "LIMIT", "MARKET", "STOP", "STOP_MARKET", - "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET" - ]), - quantity: z.string().optional(), - price: z.string().optional(), - stopPrice: z.string().optional(), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional(), - reduceOnly: z.boolean().optional(), - workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional(), - priceProtect: z.boolean().optional(), - newClientOrderId: z.string().optional() + symbol: z.string(), + side: z.enum(["BUY", "SELL"]), + positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional(), + type: z.enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]), + quantity: z.string().optional(), + price: z.string().optional(), + stopPrice: z.string().optional(), + timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional(), + reduceOnly: z.boolean().optional(), + workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional(), + priceProtect: z.boolean().optional(), + newClientOrderId: z.string().optional(), }); export function registerBinanceFuturesBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesBatchOrders", + server.registerTool( + "BinanceFuturesBatchOrders", + { + description: "Place multiple USD-M Futures orders in a batch (max 5 orders). ⚠️ RISK: Futures trading involves leverage and liquidation risk.", - { - batchOrders: z.array(orderSchema).max(5).describe("Array of orders (max 5). Each order has: symbol, side, type, quantity, price, etc."), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.placeMultipleOrders({ - batchOrders: JSON.stringify(params.batchOrders), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const results = Array.isArray(data) ? data.map((order: any, index: number) => { - if (order.orderId) { - return `Order ${index + 1}: ✅ ${order.symbol} ${order.side} ${order.type} - ID: ${order.orderId}`; - } else { - return `Order ${index + 1}: ❌ Failed - ${order.msg || 'Unknown error'}`; - } - }).join('\n') : 'Unexpected response format'; - - return { - content: [{ - type: "text", - text: `Batch Order Results:\n${results}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place batch orders: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + batchOrders: z + .array(orderSchema) + .max(5) + .describe( + "Array of orders (max 5). Each order has: symbol, side, type, quantity, price, etc.", + ), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.placeMultipleOrders({ + batchOrders: JSON.stringify(params.batchOrders), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const results = Array.isArray(data) + ? data + .map((order: any, index: number) => { + if (order.orderId) { + return `Order ${index + 1}: ✅ ${order.symbol} ${order.side} ${order.type} - ID: ${order.orderId}`; + } else { + return `Order ${index + 1}: ❌ Failed - ${order.msg || "Unknown error"}`; + } + }) + .join("\n") + : "Unexpected response format"; + + return { + content: [ + { + type: "text", + text: `Batch Order Results:\n${results}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place batch orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/cancelAllOpenOrders.ts b/src/tools/binance-futures-usdm/trade-api/cancelAllOpenOrders.ts index ef0297a8..d43babf5 100644 --- a/src/tools/binance-futures-usdm/trade-api/cancelAllOpenOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/cancelAllOpenOrders.ts @@ -5,41 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/cancelAllOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesCancelAllOpenOrders(server: McpServer) { - server.tool( - "BinanceFuturesCancelAllOpenOrders", + server.registerTool( + "BinanceFuturesCancelAllOpenOrders", + { + description: "Cancel all open orders for a symbol. Use with caution as this cancels ALL open orders.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.cancelAllOpenOrders(params.symbol); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.cancelAllOpenOrders({ + symbol: params.symbol, + }); + + return { + content: [ + { + type: "text" as const, + text: JSON.stringify(response.data, null, 2), + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: JSON.stringify(response.data, null, 2) - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: `Error canceling all futures orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text" as const, + text: `Error canceling all futures orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/cancelAllOrders.ts b/src/tools/binance-futures-usdm/trade-api/cancelAllOrders.ts index 1426b7e5..9183cf01 100644 --- a/src/tools/binance-futures-usdm/trade-api/cancelAllOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/cancelAllOrders.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCancelAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesCancelAllOrders", + server.registerTool( + "BinanceFuturesCancelAllOrders", + { + description: "Cancel all open USD-M Futures orders for a symbol. ⚠️ This will cancel ALL open orders for the specified symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.cancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ All open orders cancelled for ${params.symbol}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.cancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ All open orders cancelled for ${params.symbol}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/cancelBatchOrders.ts b/src/tools/binance-futures-usdm/trade-api/cancelBatchOrders.ts index 1bb5885e..75886962 100644 --- a/src/tools/binance-futures-usdm/trade-api/cancelBatchOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/cancelBatchOrders.ts @@ -5,61 +5,87 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceFuturesCancelBatchOrders", - "Cancel multiple USD-M Futures orders in batch (max 10 orders).", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderIdList: z.array(z.number().int()).max(10).optional().describe("List of order IDs to cancel (max 10)"), - origClientOrderIdList: z.array(z.string()).max(10).optional().describe("List of client order IDs to cancel (max 10)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderIdList && !params.origClientOrderIdList) { - return { - content: [{ type: "text", text: "Either orderIdList or origClientOrderIdList must be provided" }], - isError: true - }; - } - - const response = await futuresClient.restAPI.cancelMultipleOrders({ - symbol: params.symbol, - ...(params.orderIdList && { orderIdList: JSON.stringify(params.orderIdList) }), - ...(params.origClientOrderIdList && { origClientOrderIdList: JSON.stringify(params.origClientOrderIdList) }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const results = Array.isArray(data) ? data.map((order: any, index: number) => { - if (order.orderId && order.status === 'CANCELED') { - return `Order ${index + 1}: ✅ Cancelled - ID: ${order.orderId}`; - } else if (order.code) { - return `Order ${index + 1}: ❌ Failed - ${order.msg || 'Unknown error'}`; - } else { - return `Order ${index + 1}: ${order.status} - ID: ${order.orderId}`; - } - }).join('\n') : 'Unexpected response format'; - - return { - content: [{ - type: "text", - text: `Batch Cancel Results:\n${results}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel batch orders: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceFuturesCancelBatchOrders", + { + description: "Cancel multiple USD-M Futures orders in batch (max 10 orders).", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderIdList: z + .array(z.number().int()) + .max(10) + .optional() + .describe("List of order IDs to cancel (max 10)"), + origClientOrderIdList: z + .array(z.string()) + .max(10) + .optional() + .describe("List of client order IDs to cancel (max 10)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderIdList && !params.origClientOrderIdList) { + return { + content: [ + { + type: "text", + text: "Either orderIdList or origClientOrderIdList must be provided", + }, + ], + isError: true, + }; } - ); + + const response = await futuresClient.restAPI.cancelMultipleOrders({ + symbol: params.symbol, + ...(params.orderIdList && { orderIdList: JSON.stringify(params.orderIdList) }), + ...(params.origClientOrderIdList && { + origClientOrderIdList: JSON.stringify(params.origClientOrderIdList), + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const results = Array.isArray(data) + ? data + .map((order: any, index: number) => { + if (order.orderId && order.status === "CANCELED") { + return `Order ${index + 1}: ✅ Cancelled - ID: ${order.orderId}`; + } else if (order.code) { + return `Order ${index + 1}: ❌ Failed - ${order.msg || "Unknown error"}`; + } else { + return `Order ${index + 1}: ${order.status} - ID: ${order.orderId}`; + } + }) + .join("\n") + : "Unexpected response format"; + + return { + content: [ + { + type: "text", + text: `Batch Cancel Results:\n${results}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel batch orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/cancelOrder.ts b/src/tools/binance-futures-usdm/trade-api/cancelOrder.ts index 7191da19..3a0e0d67 100644 --- a/src/tools/binance-futures-usdm/trade-api/cancelOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/cancelOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCancelOrder(server: McpServer) { - server.tool( - "BinanceFuturesCancelOrder", - "Cancel a specific USD-M Futures order by orderId or origClientOrderId.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await futuresClient.restAPI.cancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Order cancelled successfully!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to cancel order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceFuturesCancelOrder", + { + description: "Cancel a specific USD-M Futures order by orderId or origClientOrderId.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await futuresClient.restAPI.cancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Order cancelled successfully!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/changeLeverage.ts b/src/tools/binance-futures-usdm/trade-api/changeLeverage.ts index 28b0c255..2b57aad0 100644 --- a/src/tools/binance-futures-usdm/trade-api/changeLeverage.ts +++ b/src/tools/binance-futures-usdm/trade-api/changeLeverage.ts @@ -5,42 +5,55 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/changeLeverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesChangeLeverage(server: McpServer) { - server.tool( - "BinanceFuturesChangeLeverage", + server.registerTool( + "BinanceFuturesChangeLeverage", + { + description: "Change the initial leverage for a USD-M Futures symbol. Max leverage depends on notional value tier. ⚠️ Higher leverage increases both profit potential and liquidation risk.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - leverage: z.number().int().min(1).max(125).describe("Target leverage (1-125, actual max depends on symbol)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changeInitialLeverage({ - symbol: params.symbol, - leverage: params.leverage, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Leverage changed successfully!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change leverage: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + leverage: z + .number() + .int() + .min(1) + .max(125) + .describe("Target leverage (1-125, actual max depends on symbol)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changeInitialLeverage({ + symbol: params.symbol, + leverage: params.leverage, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Leverage changed successfully!\n\nSymbol: ${data.symbol}\nNew Leverage: ${data.leverage}x\nMax Notional Value: ${data.maxNotionalValue}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change leverage: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/changeMarginType.ts b/src/tools/binance-futures-usdm/trade-api/changeMarginType.ts index 23878792..4ec76e95 100644 --- a/src/tools/binance-futures-usdm/trade-api/changeMarginType.ts +++ b/src/tools/binance-futures-usdm/trade-api/changeMarginType.ts @@ -5,42 +5,54 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/changeMarginType.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesChangeMarginType(server: McpServer) { - server.tool( - "BinanceFuturesChangeMarginType", + server.registerTool( + "BinanceFuturesChangeMarginType", + { + description: "Change margin type between ISOLATED and CROSSED for a USD-M Futures symbol. ISOLATED: Position uses its own margin. CROSSED: All positions share account margin.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - marginType: z.enum(["ISOLATED", "CROSSED"]).describe("ISOLATED: Separate margin per position. CROSSED: Shared margin across positions"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changeMarginType({ - symbol: params.symbol, - marginType: params.marginType, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Margin type changed successfully!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change margin type: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + marginType: z + .enum(["ISOLATED", "CROSSED"]) + .describe( + "ISOLATED: Separate margin per position. CROSSED: Shared margin across positions", + ), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changeMarginType({ + symbol: params.symbol, + marginType: params.marginType, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Margin type changed successfully!\n\nSymbol: ${params.symbol}\nNew Margin Type: ${params.marginType}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change margin type: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/changeMultiAssetsMode.ts b/src/tools/binance-futures-usdm/trade-api/changeMultiAssetsMode.ts index 48d9242c..c4849950 100644 --- a/src/tools/binance-futures-usdm/trade-api/changeMultiAssetsMode.ts +++ b/src/tools/binance-futures-usdm/trade-api/changeMultiAssetsMode.ts @@ -5,41 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/changeMultiAssetsMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesChangeMultiAssetsMode(server: McpServer) { - server.tool( - "BinanceFuturesChangeMultiAssetsMode", + server.registerTool( + "BinanceFuturesChangeMultiAssetsMode", + { + description: "Change Multi-Assets Mode setting. When enabled, margin from multiple assets (USDT, BUSD) can be used to avoid liquidation.", - { - multiAssetsMargin: z.boolean().describe("true = Enable Multi-Assets Mode, false = Disable"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changeMultiAssetsMode({ - multiAssetsMargin: params.multiAssetsMargin, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const mode = params.multiAssetsMargin ? "Enabled" : "Disabled"; - - return { - content: [{ - type: "text", - text: `✅ Multi-Assets Mode ${mode}!\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change multi-assets mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + multiAssetsMargin: z.boolean().describe("true = Enable Multi-Assets Mode, false = Disable"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changeMultiAssetsMode({ + multiAssetsMargin: params.multiAssetsMargin, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const mode = params.multiAssetsMargin ? "Enabled" : "Disabled"; + + return { + content: [ + { + type: "text", + text: `✅ Multi-Assets Mode ${mode}!\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to change multi-assets mode: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/changePositionMode.ts b/src/tools/binance-futures-usdm/trade-api/changePositionMode.ts index 9e848ee6..751f16ae 100644 --- a/src/tools/binance-futures-usdm/trade-api/changePositionMode.ts +++ b/src/tools/binance-futures-usdm/trade-api/changePositionMode.ts @@ -5,41 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/changePositionMode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesChangePositionMode(server: McpServer) { - server.tool( - "BinanceFuturesChangePositionMode", + server.registerTool( + "BinanceFuturesChangePositionMode", + { + description: "Change position mode between Hedge Mode and One-way Mode. HEDGE: Can hold both LONG and SHORT positions simultaneously. ONE-WAY: Only one direction at a time (positionSide=BOTH).", - { - dualSidePosition: z.boolean().describe("true = Hedge Mode (Long/Short), false = One-way Mode (BOTH)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.changePositionMode({ - dualSidePosition: params.dualSidePosition, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const mode = params.dualSidePosition ? "Hedge Mode (LONG/SHORT)" : "One-way Mode (BOTH)"; - - return { - content: [{ - type: "text", - text: `✅ Position mode changed successfully!\n\nNew Mode: ${mode}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to change position mode: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + dualSidePosition: z + .boolean() + .describe("true = Hedge Mode (Long/Short), false = One-way Mode (BOTH)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.changePositionMode({ + dualSidePosition: params.dualSidePosition, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const mode = params.dualSidePosition ? "Hedge Mode (LONG/SHORT)" : "One-way Mode (BOTH)"; + + return { + content: [ + { + type: "text", + text: `✅ Position mode changed successfully!\n\nNew Mode: ${mode}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to change position mode: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/countdownCancelAll.ts b/src/tools/binance-futures-usdm/trade-api/countdownCancelAll.ts index 2b808e49..335a4d5e 100644 --- a/src/tools/binance-futures-usdm/trade-api/countdownCancelAll.ts +++ b/src/tools/binance-futures-usdm/trade-api/countdownCancelAll.ts @@ -5,46 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/countdownCancelAll.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCountdownCancelAll(server: McpServer) { - server.tool( - "BinanceFuturesCountdownCancelAll", + server.registerTool( + "BinanceFuturesCountdownCancelAll", + { + description: "Set auto-cancel all open orders after countdown. Use as dead man's switch for protection. ⚠️ System will cancel orders automatically if no heartbeat received.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - countdownTime: z.number().int().describe("Countdown time in milliseconds. 0 to cancel the countdown."), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.autoCancelAllOpenOrders({ - symbol: params.symbol, - countdownTime: params.countdownTime, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const message = params.countdownTime === 0 - ? `✅ Countdown cancelled for ${params.symbol}` - : `✅ Countdown set for ${params.symbol}\nOrders will be cancelled in ${params.countdownTime}ms if no heartbeat received`; - - return { - content: [{ - type: "text", - text: `${message}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to set countdown: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + countdownTime: z + .number() + .int() + .describe("Countdown time in milliseconds. 0 to cancel the countdown."), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.autoCancelAllOpenOrders({ + symbol: params.symbol, + countdownTime: params.countdownTime, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const message = + params.countdownTime === 0 + ? `✅ Countdown cancelled for ${params.symbol}` + : `✅ Countdown set for ${params.symbol}\nOrders will be cancelled in ${params.countdownTime}ms if no heartbeat received`; + + return { + content: [ + { + type: "text", + text: `${message}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to set countdown: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/getAllOrders.ts b/src/tools/binance-futures-usdm/trade-api/getAllOrders.ts index 8f53d303..baca051e 100644 --- a/src/tools/binance-futures-usdm/trade-api/getAllOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/getAllOrders.ts @@ -5,50 +5,62 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/getAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesGetAllOrders(server: McpServer) { - server.tool( - "BinanceFuturesGetAllOrders", - "Get all USD-M Futures orders (active, canceled, or filled) for a symbol.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("If set, get orders >= this orderId"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().max(1000).optional().describe("Number of orders. Default 500, max 1000"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.allOrders({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const orderCount = Array.isArray(data) ? data.length : 0; - - return { - content: [{ - type: "text", - text: `All Orders for ${params.symbol}: ${orderCount} orders\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesGetAllOrders", + { + description: "Get all USD-M Futures orders (active, canceled, or filled) for a symbol.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("If set, get orders >= this orderId"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(1000) + .optional() + .describe("Number of orders. Default 500, max 1000"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.allOrders({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const orderCount = Array.isArray(data) ? data.length : 0; + + return { + content: [ + { + type: "text", + text: `All Orders for ${params.symbol}: ${orderCount} orders\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/getOpenOrder.ts b/src/tools/binance-futures-usdm/trade-api/getOpenOrder.ts index dc760258..9c8fa380 100644 --- a/src/tools/binance-futures-usdm/trade-api/getOpenOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/getOpenOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/getOpenOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesGetOpenOrder(server: McpServer) { - server.tool( - "BinanceFuturesGetOpenOrder", - "Query a specific open USD-M Futures order by orderId or origClientOrderId.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await futuresClient.restAPI.queryCurrentOpenOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `Open Order Details:\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSide: ${data.side}\nType: ${data.type}\nStatus: ${data.status}\nPrice: ${data.price}\nQty: ${data.origQty}\nExecuted Qty: ${data.executedQty}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query open order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceFuturesGetOpenOrder", + { + description: "Query a specific open USD-M Futures order by orderId or origClientOrderId.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await futuresClient.restAPI.queryCurrentOpenOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Open Order Details:\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSide: ${data.side}\nType: ${data.type}\nStatus: ${data.status}\nPrice: ${data.price}\nQty: ${data.origQty}\nExecuted Qty: ${data.executedQty}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to query open order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/getOpenOrders.ts b/src/tools/binance-futures-usdm/trade-api/getOpenOrders.ts index f11a8680..f9668460 100644 --- a/src/tools/binance-futures-usdm/trade-api/getOpenOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/getOpenOrders.ts @@ -5,47 +5,61 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesGetOpenOrders(server: McpServer) { - server.tool( - "BinanceFuturesGetOpenOrders", - "Get all open USD-M Futures orders for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Futures symbol (e.g., BTCUSDT). If not provided, returns all open orders"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.currentAllOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - const orderCount = Array.isArray(data) ? data.length : 0; - const orderSummary = Array.isArray(data) && data.length > 0 - ? data.map((order: any) => - `${order.symbol} ${order.side} ${order.type} ${order.origQty}@${order.price} (ID: ${order.orderId})` - ).join('\n') - : 'No open orders'; - - return { - content: [{ - type: "text", - text: `Open Orders${params.symbol ? ` for ${params.symbol}` : ''}: ${orderCount}\n\n${orderSummary}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceFuturesGetOpenOrders", + { + description: "Get all open USD-M Futures orders for a symbol or all symbols.", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Futures symbol (e.g., BTCUSDT). If not provided, returns all open orders"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.currentAllOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + const orderCount = Array.isArray(data) ? data.length : 0; + const orderSummary = + Array.isArray(data) && data.length > 0 + ? data + .map( + (order: any) => + `${order.symbol} ${order.side} ${order.type} ${order.origQty}@${order.price} (ID: ${order.orderId})`, + ) + .join("\n") + : "No open orders"; + + return { + content: [ + { + type: "text", + text: `Open Orders${params.symbol ? ` for ${params.symbol}` : ""}: ${orderCount}\n\n${orderSummary}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/getOrder.ts b/src/tools/binance-futures-usdm/trade-api/getOrder.ts index 2e992695..7fffb442 100644 --- a/src/tools/binance-futures-usdm/trade-api/getOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/getOrder.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesGetOrder(server: McpServer) { - server.tool( - "BinanceFuturesGetOrder", - "Query a specific USD-M Futures order by orderId or origClientOrderId.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await futuresClient.restAPI.queryOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `Order Details:\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSide: ${data.side}\nType: ${data.type}\nStatus: ${data.status}\nPrice: ${data.price}\nQty: ${data.origQty}\nExecuted Qty: ${data.executedQty}\nAvg Price: ${data.avgPrice}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceFuturesGetOrder", + { + description: "Query a specific USD-M Futures order by orderId or origClientOrderId.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await futuresClient.restAPI.queryOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Order Details:\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSide: ${data.side}\nType: ${data.type}\nStatus: ${data.status}\nPrice: ${data.price}\nQty: ${data.origQty}\nExecuted Qty: ${data.executedQty}\nAvg Price: ${data.avgPrice}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to query order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/index.ts b/src/tools/binance-futures-usdm/trade-api/index.ts index d32c5ac1..39522866 100644 --- a/src/tools/binance-futures-usdm/trade-api/index.ts +++ b/src/tools/binance-futures-usdm/trade-api/index.ts @@ -5,50 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceFuturesNewOrder } from "./newOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceFuturesBatchOrders } from "./batchOrders.js"; -import { registerBinanceFuturesGetOrder } from "./getOrder.js"; -import { registerBinanceFuturesCancelOrder } from "./cancelOrder.js"; import { registerBinanceFuturesCancelAllOrders } from "./cancelAllOrders.js"; import { registerBinanceFuturesCancelBatchOrders } from "./cancelBatchOrders.js"; +import { registerBinanceFuturesCancelOrder } from "./cancelOrder.js"; +import { registerBinanceFuturesChangeLeverage } from "./changeLeverage.js"; +import { registerBinanceFuturesChangeMarginType } from "./changeMarginType.js"; +import { registerBinanceFuturesChangeMultiAssetsMode } from "./changeMultiAssetsMode.js"; +import { registerBinanceFuturesChangePositionMode } from "./changePositionMode.js"; import { registerBinanceFuturesCountdownCancelAll } from "./countdownCancelAll.js"; +import { registerBinanceFuturesGetAllOrders } from "./getAllOrders.js"; import { registerBinanceFuturesGetOpenOrder } from "./getOpenOrder.js"; import { registerBinanceFuturesGetOpenOrders } from "./getOpenOrders.js"; -import { registerBinanceFuturesGetAllOrders } from "./getAllOrders.js"; -import { registerBinanceFuturesModifyOrder } from "./modifyOrder.js"; -import { registerBinanceFuturesChangeLeverage } from "./changeLeverage.js"; -import { registerBinanceFuturesChangeMarginType } from "./changeMarginType.js"; +import { registerBinanceFuturesGetOrder } from "./getOrder.js"; import { registerBinanceFuturesModifyIsolatedPositionMargin } from "./modifyIsolatedPositionMargin.js"; +import { registerBinanceFuturesModifyOrder } from "./modifyOrder.js"; +import { registerBinanceFuturesNewOrder } from "./newOrder.js"; import { registerBinanceFuturesPositionMarginHistory } from "./positionMarginHistory.js"; -import { registerBinanceFuturesChangePositionMode } from "./changePositionMode.js"; -import { registerBinanceFuturesChangeMultiAssetsMode } from "./changeMultiAssetsMode.js"; export function registerBinanceFuturesTradeApiTools(server: McpServer) { - // Order Placement - registerBinanceFuturesNewOrder(server); - registerBinanceFuturesBatchOrders(server); - registerBinanceFuturesModifyOrder(server); - - // Order Query - registerBinanceFuturesGetOrder(server); - registerBinanceFuturesGetOpenOrder(server); - registerBinanceFuturesGetOpenOrders(server); - registerBinanceFuturesGetAllOrders(server); - - // Order Cancellation - registerBinanceFuturesCancelOrder(server); - registerBinanceFuturesCancelAllOrders(server); - registerBinanceFuturesCancelBatchOrders(server); - registerBinanceFuturesCountdownCancelAll(server); - - // Leverage & Margin - registerBinanceFuturesChangeLeverage(server); - registerBinanceFuturesChangeMarginType(server); - registerBinanceFuturesModifyIsolatedPositionMargin(server); - registerBinanceFuturesPositionMarginHistory(server); - - // Position & Asset Modes - registerBinanceFuturesChangePositionMode(server); - registerBinanceFuturesChangeMultiAssetsMode(server); + // Order Placement + registerBinanceFuturesNewOrder(server); + registerBinanceFuturesBatchOrders(server); + registerBinanceFuturesModifyOrder(server); + + // Order Query + registerBinanceFuturesGetOrder(server); + registerBinanceFuturesGetOpenOrder(server); + registerBinanceFuturesGetOpenOrders(server); + registerBinanceFuturesGetAllOrders(server); + + // Order Cancellation + registerBinanceFuturesCancelOrder(server); + registerBinanceFuturesCancelAllOrders(server); + registerBinanceFuturesCancelBatchOrders(server); + registerBinanceFuturesCountdownCancelAll(server); + + // Leverage & Margin + registerBinanceFuturesChangeLeverage(server); + registerBinanceFuturesChangeMarginType(server); + registerBinanceFuturesModifyIsolatedPositionMargin(server); + registerBinanceFuturesPositionMarginHistory(server); + + // Position & Asset Modes + registerBinanceFuturesChangePositionMode(server); + registerBinanceFuturesChangeMultiAssetsMode(server); } diff --git a/src/tools/binance-futures-usdm/trade-api/modifyIsolatedPositionMargin.ts b/src/tools/binance-futures-usdm/trade-api/modifyIsolatedPositionMargin.ts index 32bef2de..d57510fe 100644 --- a/src/tools/binance-futures-usdm/trade-api/modifyIsolatedPositionMargin.ts +++ b/src/tools/binance-futures-usdm/trade-api/modifyIsolatedPositionMargin.ts @@ -5,47 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/modifyIsolatedPositionMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesModifyIsolatedPositionMargin(server: McpServer) { - server.tool( - "BinanceFuturesModifyIsolatedPositionMargin", + server.registerTool( + "BinanceFuturesModifyIsolatedPositionMargin", + { + description: "Add or reduce margin to/from an isolated margin position. Only works when margin type is ISOLATED.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - amount: z.string().describe("Amount of margin to add or reduce"), - type: z.enum(["1", "2"]).describe("1 = Add margin, 2 = Reduce margin"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode (default BOTH)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.modifyIsolatedPositionMargin({ - symbol: params.symbol, - amount: params.amount, - type: parseInt(params.type) as 1 | 2, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - const action = params.type === "1" ? "added to" : "reduced from"; - - return { - content: [{ - type: "text", - text: `✅ Margin ${action} position successfully!\n\nSymbol: ${params.symbol}\nAmount: ${params.amount}\nAction: ${params.type === "1" ? "Add" : "Reduce"}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to modify isolated position margin: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + amount: z.string().describe("Amount of margin to add or reduce"), + type: z.enum(["1", "2"]).describe("1 = Add margin, 2 = Reduce margin"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for Hedge Mode (default BOTH)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.modifyIsolatedPositionMargin({ + symbol: params.symbol, + amount: params.amount, + type: parseInt(params.type) as 1 | 2, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + const action = params.type === "1" ? "added to" : "reduced from"; + + return { + content: [ + { + type: "text", + text: `✅ Margin ${action} position successfully!\n\nSymbol: ${params.symbol}\nAmount: ${params.amount}\nAction: ${params.type === "1" ? "Add" : "Reduce"}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to modify isolated position margin: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/modifyOrder.ts b/src/tools/binance-futures-usdm/trade-api/modifyOrder.ts index de7c2641..010898f1 100644 --- a/src/tools/binance-futures-usdm/trade-api/modifyOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/modifyOrder.ts @@ -5,59 +5,80 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/modifyOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesModifyOrder(server: McpServer) { - server.tool( - "BinanceFuturesModifyOrder", - "Modify an existing USD-M Futures order. Can modify price, quantity, or both.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - quantity: z.string().optional().describe("New quantity"), - price: z.string().optional().describe("New price"), - priceMatch: z.enum(["OPPONENT", "OPPONENT_5", "OPPONENT_10", "OPPONENT_20", "QUEUE", "QUEUE_5", "QUEUE_10", "QUEUE_20"]).optional().describe("Price match mode"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Either orderId or origClientOrderId must be provided" }], - isError: true - }; - } - - const response = await futuresClient.restAPI.modifyOrder({ - symbol: params.symbol, - side: params.side, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.priceMatch && { priceMatch: params.priceMatch }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Order modified successfully!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nSide: ${data.side}\nNew Price: ${data.price}\nNew Qty: ${data.origQty}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to modify order: ${errorMessage}` }], - isError: true - }; - } + server.registerTool( + "BinanceFuturesModifyOrder", + { + description: "Modify an existing USD-M Futures order. Can modify price, quantity, or both.", + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + quantity: z.string().optional().describe("New quantity"), + price: z.string().optional().describe("New price"), + priceMatch: z + .enum([ + "OPPONENT", + "OPPONENT_5", + "OPPONENT_10", + "OPPONENT_20", + "QUEUE", + "QUEUE_5", + "QUEUE_10", + "QUEUE_20", + ]) + .optional() + .describe("Price match mode"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderId or origClientOrderId must be provided" }, + ], + isError: true, + }; } - ); + + const response = await futuresClient.restAPI.modifyOrder({ + symbol: params.symbol, + side: params.side, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.priceMatch && { priceMatch: params.priceMatch }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Order modified successfully!\n\nSymbol: ${data.symbol}\nOrder ID: ${data.orderId}\nSide: ${data.side}\nNew Price: ${data.price}\nNew Qty: ${data.origQty}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to modify order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/newOrder.ts b/src/tools/binance-futures-usdm/trade-api/newOrder.ts index c12b8cfc..e85ff613 100644 --- a/src/tools/binance-futures-usdm/trade-api/newOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/newOrder.ts @@ -5,76 +5,116 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesNewOrder(server: McpServer) { - server.tool( - "BinanceFuturesNewOrder", + server.registerTool( + "BinanceFuturesNewOrder", + { + description: "Place a new USD-M Futures order. Supports LIMIT, MARKET, STOP, TAKE_PROFIT, and TRAILING_STOP_MARKET orders. ⚠️ RISK: Futures trading involves leverage and liquidation risk.", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side for Hedge Mode. Use BOTH for One-Way Mode"), - type: z.enum([ - "LIMIT", "MARKET", "STOP", "STOP_MARKET", - "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET" - ]).describe("Order type"), - quantity: z.string().optional().describe("Order quantity"), - price: z.string().optional().describe("Limit price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), - timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force. GTC=Good Till Cancel, IOC=Immediate Or Cancel, FOK=Fill Or Kill, GTX=Good Till Crossing"), - reduceOnly: z.boolean().optional().describe("Reduce position only (cannot be used with closePosition)"), - closePosition: z.boolean().optional().describe("Close entire position (cannot be used with quantity or reduceOnly)"), - activationPrice: z.string().optional().describe("Activation price for TRAILING_STOP_MARKET"), - callbackRate: z.string().optional().describe("Callback rate for TRAILING_STOP_MARKET (0.1% - 5%)"), - workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional().describe("Stop price trigger type"), - priceProtect: z.boolean().optional().describe("Price protection"), - newClientOrderId: z.string().optional().describe("Custom order ID"), - newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.newOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.positionSide && { positionSide: params.positionSide }), - ...(params.quantity && { quantity: params.quantity }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), - ...(params.closePosition !== undefined && { closePosition: params.closePosition }), - ...(params.activationPrice && { activationPrice: params.activationPrice }), - ...(params.callbackRate && { callbackRate: params.callbackRate }), - ...(params.workingType && { workingType: params.workingType }), - ...(params.priceProtect !== undefined && { priceProtect: params.priceProtect }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Futures order placed successfully!\n\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nPosition Side: ${data.positionSide || 'BOTH'}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || 'MARKET'}\nStop Price: ${data.stopPrice || 'N/A'}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `❌ Failed to place futures order: ${errorMessage}` - }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + positionSide: z + .enum(["BOTH", "LONG", "SHORT"]) + .optional() + .describe("Position side for Hedge Mode. Use BOTH for One-Way Mode"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP", + "STOP_MARKET", + "TAKE_PROFIT", + "TAKE_PROFIT_MARKET", + "TRAILING_STOP_MARKET", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity"), + price: z.string().optional().describe("Limit price (required for LIMIT orders)"), + stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), + timeInForce: z + .enum(["GTC", "IOC", "FOK", "GTX"]) + .optional() + .describe( + "Time in force. GTC=Good Till Cancel, IOC=Immediate Or Cancel, FOK=Fill Or Kill, GTX=Good Till Crossing", + ), + reduceOnly: z + .boolean() + .optional() + .describe("Reduce position only (cannot be used with closePosition)"), + closePosition: z + .boolean() + .optional() + .describe("Close entire position (cannot be used with quantity or reduceOnly)"), + activationPrice: z + .string() + .optional() + .describe("Activation price for TRAILING_STOP_MARKET"), + callbackRate: z + .string() + .optional() + .describe("Callback rate for TRAILING_STOP_MARKET (0.1% - 5%)"), + workingType: z + .enum(["MARK_PRICE", "CONTRACT_PRICE"]) + .optional() + .describe("Stop price trigger type"), + priceProtect: z.boolean().optional().describe("Price protection"), + newClientOrderId: z.string().optional().describe("Custom order ID"), + newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.newOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.positionSide && { positionSide: params.positionSide }), + ...(params.quantity && { quantity: params.quantity }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.reduceOnly !== undefined && { reduceOnly: params.reduceOnly }), + ...(params.closePosition !== undefined && { closePosition: params.closePosition }), + ...(params.activationPrice && { activationPrice: params.activationPrice }), + ...(params.callbackRate && { callbackRate: params.callbackRate }), + ...(params.workingType && { workingType: params.workingType }), + ...(params.priceProtect !== undefined && { priceProtect: params.priceProtect }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Futures order placed successfully!\n\nOrder ID: ${data.orderId}\nClient Order ID: ${data.clientOrderId}\nSymbol: ${data.symbol}\nSide: ${data.side}\nPosition Side: ${data.positionSide || "BOTH"}\nType: ${data.type}\nQuantity: ${data.origQty}\nPrice: ${data.price || "MARKET"}\nStop Price: ${data.stopPrice || "N/A"}\nStatus: ${data.status}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `❌ Failed to place futures order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/openOrder.ts b/src/tools/binance-futures-usdm/trade-api/openOrder.ts index 39139b79..552806a3 100644 --- a/src/tools/binance-futures-usdm/trade-api/openOrder.ts +++ b/src/tools/binance-futures-usdm/trade-api/openOrder.ts @@ -5,61 +5,65 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/openOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesOpenOrder(server: McpServer) { - server.tool( - "BinanceFuturesOpenOrder", + server.registerTool( + "BinanceFuturesOpenOrder", + { + description: "Query a single open order. Either orderId or origClientOrderId must be provided.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - return { - content: [ - { - type: "text" as const, - text: "Error: Either orderId or origClientOrderId must be provided" - } - ], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { + type: "text" as const, + text: "Error: Either orderId or origClientOrderId must be provided", + }, + ], + isError: true, + }; + } - const response = await futuresClient.restAPI.currentOpenOrder( - params.symbol, - { - orderId: params.orderId, - origClientOrderId: params.origClientOrderId - } - ); + const response = await futuresClient.restAPI.currentOpenOrder({ + symbol: params.symbol, + orderId: params.orderId, + origClientOrderId: params.origClientOrderId, + }); - return { - content: [ - { - type: "text" as const, - text: JSON.stringify(response.data, null, 2) - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: `Error getting open order: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text" as const, + text: JSON.stringify(response.data, null, 2), + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; + + return { + content: [ + { + type: "text" as const, + text: `Error getting open order: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/openOrders.ts b/src/tools/binance-futures-usdm/trade-api/openOrders.ts index fc422b14..9a9c33eb 100644 --- a/src/tools/binance-futures-usdm/trade-api/openOrders.ts +++ b/src/tools/binance-futures-usdm/trade-api/openOrders.ts @@ -5,43 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/openOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../../config/binanceClient.js"; export function registerBinanceFuturesOpenOrders(server: McpServer) { - server.tool( - "BinanceFuturesOpenOrders", + server.registerTool( + "BinanceFuturesOpenOrders", + { + description: "Get all current open orders. If symbol is provided, returns orders for that symbol only. Otherwise returns all open orders (use with caution due to rate limits).", - { - symbol: z.string().optional().describe("Trading pair symbol (e.g., BTCUSDT). If omitted, returns all open orders.") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.currentAllOpenOrders({ - symbol: params.symbol - }); + inputSchema: { + symbol: z + .string() + .optional() + .describe("Trading pair symbol (e.g., BTCUSDT). If omitted, returns all open orders."), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.currentAllOpenOrders({ + symbol: params.symbol, + }); + + return { + content: [ + { + type: "text" as const, + text: JSON.stringify(response.data, null, 2), + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: JSON.stringify(response.data, null, 2) - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; - return { - content: [ - { - type: "text" as const, - text: `Error getting open orders: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text" as const, + text: `Error getting open orders: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trade-api/positionMarginHistory.ts b/src/tools/binance-futures-usdm/trade-api/positionMarginHistory.ts index 095f2b89..c751a0c9 100644 --- a/src/tools/binance-futures-usdm/trade-api/positionMarginHistory.ts +++ b/src/tools/binance-futures-usdm/trade-api/positionMarginHistory.ts @@ -5,48 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/trade-api/positionMarginHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesPositionMarginHistory(server: McpServer) { - server.tool( - "BinanceFuturesPositionMarginHistory", + server.registerTool( + "BinanceFuturesPositionMarginHistory", + { + description: "Get the history of isolated position margin changes (additions and reductions).", - { - symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), - type: z.enum(["1", "2"]).optional().describe("1 = Add margin, 2 = Reduce margin (filter)"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.getPositionMarginHistory({ - symbol: params.symbol, - ...(params.type && { type: parseInt(params.type) }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Position Margin History for ${params.symbol}\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get position margin history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + symbol: z.string().describe("Futures symbol (e.g., BTCUSDT)"), + type: z.enum(["1", "2"]).optional().describe("1 = Add margin, 2 = Reduce margin (filter)"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.getPositionMarginHistory({ + symbol: params.symbol, + ...(params.type && { type: parseInt(params.type) }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Position Margin History for ${params.symbol}\n\nRecords: ${Array.isArray(data) ? data.length : 0}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to get position margin history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/trades.ts b/src/tools/binance-futures-usdm/trades.ts index 9251c4d9..f6ad3d76 100644 --- a/src/tools/binance-futures-usdm/trades.ts +++ b/src/tools/binance-futures-usdm/trades.ts @@ -1,41 +1,48 @@ // src/tools/binance-futures-usdm/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMTrades(server: McpServer) { - server.tool( - "BinanceFuturesUSDMTrades", - "Get recent trades for a specific USD-M Futures trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMTrades", + { + description: "Get recent trades for a specific USD-M Futures trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Number of trades to return. Default 500; max 1000"), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.trades(params); - const data = await futuresClient.trades(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} recent trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} recent trades for USD-M Futures ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures recent trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve USD-M Futures recent trades: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/userTrades.ts b/src/tools/binance-futures-usdm/userTrades.ts index 03f9d7af..81f4526d 100644 --- a/src/tools/binance-futures-usdm/userTrades.ts +++ b/src/tools/binance-futures-usdm/userTrades.ts @@ -1,49 +1,53 @@ // src/tools/binance-futures-usdm/userTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { futuresClient } from "../../config/binanceClient.js"; export function registerBinanceFuturesUSDMUserTrades(server: McpServer) { - server.tool( - "BinanceFuturesUSDMUserTrades", - "Get account trade list for USD-M Futures.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Filter by order ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - fromId: z.number().optional().describe("Trade ID to start from"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, orderId, startTime, endTime, fromId, limit }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; + server.registerTool( + "BinanceFuturesUSDMUserTrades", + { + description: "Get account trade list for USD-M Futures.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Filter by order ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + fromId: z.number().optional().describe("Trade ID to start from"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, orderId, startTime, endTime, fromId, limit }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; + + const data = await futuresClient.userTrades(params); - const data = await futuresClient.userTrades(params); - + return { + content: [ + { + type: "text", + text: `Retrieved ${data.length || 0} USD-M Futures trades for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved ${data.length || 0} USD-M Futures trades for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve USD-M Futures user trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve USD-M Futures user trades: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/userdatastream-api/closeListenKey.ts b/src/tools/binance-futures-usdm/userdatastream-api/closeListenKey.ts index b41bf43b..65f895f1 100644 --- a/src/tools/binance-futures-usdm/userdatastream-api/closeListenKey.ts +++ b/src/tools/binance-futures-usdm/userdatastream-api/closeListenKey.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/userdatastream-api/closeListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCloseListenKey(server: McpServer) { - server.tool( - "BinanceFuturesCloseListenKey", + server.registerTool( + "BinanceFuturesCloseListenKey", + { + description: "Close a USD-M Futures user data stream listen key. This invalidates the listen key and closes the associated WebSocket stream.", - { - listenKey: z.string().optional().describe("Listen key to close. If not provided, closes the default listen key."), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.closeListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Listen Key Closed!\n\nThe listen key has been invalidated and the stream is closed.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to close listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z + .string() + .optional() + .describe("Listen key to close. If not provided, closes the default listen key."), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.closeListenKey(); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Listen Key Closed!\n\nThe listen key has been invalidated and the stream is closed.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to close listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/userdatastream-api/createListenKey.ts b/src/tools/binance-futures-usdm/userdatastream-api/createListenKey.ts index 050dc0f1..1ccd4f5a 100644 --- a/src/tools/binance-futures-usdm/userdatastream-api/createListenKey.ts +++ b/src/tools/binance-futures-usdm/userdatastream-api/createListenKey.ts @@ -5,38 +5,44 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/userdatastream-api/createListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesCreateListenKey(server: McpServer) { - server.tool( - "BinanceFuturesCreateListenKey", + server.registerTool( + "BinanceFuturesCreateListenKey", + { + description: "Create a new USD-M Futures user data stream listen key. The listen key is valid for 60 minutes and can be used to receive account updates via WebSocket. Must be kept alive with keepAlive endpoint.", - { - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.createListenKey({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Listen Key Created Successfully!\n\nListen Key: ${data.listenKey}\n\n⚠️ Important:\n- Valid for 60 minutes\n- Use keepAlive endpoint to extend validity\n- Use this key to connect to futures websocket stream\n\nWebSocket URL: wss://fstream.binance.com/ws/${data.listenKey}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to create listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.createListenKey(); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Listen Key Created Successfully!\n\nListen Key: ${data.listenKey}\n\n⚠️ Important:\n- Valid for 60 minutes\n- Use keepAlive endpoint to extend validity\n- Use this key to connect to futures websocket stream\n\nWebSocket URL: wss://fstream.binance.com/ws/${data.listenKey}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to create listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-futures-usdm/userdatastream-api/index.ts b/src/tools/binance-futures-usdm/userdatastream-api/index.ts index 9ea2340f..9174f5c0 100644 --- a/src/tools/binance-futures-usdm/userdatastream-api/index.ts +++ b/src/tools/binance-futures-usdm/userdatastream-api/index.ts @@ -5,14 +5,15 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/userdatastream-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceFuturesCloseListenKey } from "./closeListenKey.js"; import { registerBinanceFuturesCreateListenKey } from "./createListenKey.js"; import { registerBinanceFuturesKeepAliveListenKey } from "./keepAliveListenKey.js"; -import { registerBinanceFuturesCloseListenKey } from "./closeListenKey.js"; export function registerBinanceFuturesUserDataStreamApiTools(server: McpServer) { - // User Data Stream (Listen Key) Management - registerBinanceFuturesCreateListenKey(server); - registerBinanceFuturesKeepAliveListenKey(server); - registerBinanceFuturesCloseListenKey(server); + // User Data Stream (Listen Key) Management + registerBinanceFuturesCreateListenKey(server); + registerBinanceFuturesKeepAliveListenKey(server); + registerBinanceFuturesCloseListenKey(server); } diff --git a/src/tools/binance-futures-usdm/userdatastream-api/keepAliveListenKey.ts b/src/tools/binance-futures-usdm/userdatastream-api/keepAliveListenKey.ts index e40dcc12..ab499333 100644 --- a/src/tools/binance-futures-usdm/userdatastream-api/keepAliveListenKey.ts +++ b/src/tools/binance-futures-usdm/userdatastream-api/keepAliveListenKey.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-futures-usdm/userdatastream-api/keepAliveListenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { futuresClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { futuresClient } from "../../../config/binanceClient.js"; + export function registerBinanceFuturesKeepAliveListenKey(server: McpServer) { - server.tool( - "BinanceFuturesKeepAliveListenKey", + server.registerTool( + "BinanceFuturesKeepAliveListenKey", + { + description: "Keepalive a USD-M Futures user data stream listen key. Extends the validity by 60 minutes. Should be called every 30-50 minutes to maintain the connection.", - { - listenKey: z.string().optional().describe("Listen key to keep alive. If not provided, uses the default listen key."), - recvWindow: z.number().int().optional().describe("Recv window in milliseconds") - }, - async (params) => { - try { - const response = await futuresClient.restAPI.renewListenKey({ - ...(params.listenKey && { listenKey: params.listenKey }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Listen Key Extended!\n\nThe listen key validity has been extended by 60 minutes.\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to keepalive listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + listenKey: z + .string() + .optional() + .describe("Listen key to keep alive. If not provided, uses the default listen key."), + recvWindow: z.number().int().optional().describe("Recv window in milliseconds"), + }, + }, + async (params) => { + try { + const response = await futuresClient.restAPI.renewListenKey(); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Listen Key Extended!\n\nThe listen key validity has been extended by 60 minutes.\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to keepalive listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/buyCode.ts b/src/tools/binance-gift-card/buyCode.ts index 4e91fd6c..ede9a19c 100644 --- a/src/tools/binance-gift-card/buyCode.ts +++ b/src/tools/binance-gift-card/buyCode.ts @@ -1,42 +1,46 @@ // src/tools/binance-gift-card/buyCode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardBuyCode(server: McpServer) { - server.tool( - "BinanceGiftCardBuyCode", + server.registerTool( + "BinanceGiftCardBuyCode", + { + description: "Buy a Binance Gift Card code using another token as payment. The base token is used to purchase a gift card of the face token.", - { - baseToken: z.string().describe("The token used to pay for the gift card (e.g., USDT)"), - faceToken: z.string().describe("The token the gift card will contain (e.g., BNB)"), - baseTokenAmount: z.number().describe("The amount of base token to spend"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ baseToken, faceToken, baseTokenAmount, recvWindow }) => { - try { - const params: Record = { baseToken, faceToken, baseTokenAmount }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.buyCode(params); + inputSchema: { + baseToken: z.string().describe("The token used to pay for the gift card (e.g., USDT)"), + faceToken: z.string().describe("The token the gift card will contain (e.g., BNB)"), + baseTokenAmount: z.number().describe("The amount of base token to spend"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ baseToken, faceToken, baseTokenAmount, recvWindow }) => { + try { + const params: Record = { baseToken, faceToken, baseTokenAmount }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.buyCode(params); + + return { + content: [ + { + type: "text", + text: `Gift card purchased: ${baseTokenAmount} ${baseToken} -> ${faceToken}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Gift card purchased: ${baseTokenAmount} ${baseToken} -> ${faceToken}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to buy gift card: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to buy gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/createCode.ts b/src/tools/binance-gift-card/createCode.ts index 1e6471bc..5fa085ed 100644 --- a/src/tools/binance-gift-card/createCode.ts +++ b/src/tools/binance-gift-card/createCode.ts @@ -1,41 +1,45 @@ // src/tools/binance-gift-card/createCode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardCreateCode(server: McpServer) { - server.tool( - "BinanceGiftCardCreateCode", + server.registerTool( + "BinanceGiftCardCreateCode", + { + description: "Create a Binance Gift Card code. This allows you to generate a gift card with a specified token and amount.", - { - token: z.string().describe("The token to include in the gift card (e.g., BNB, USDT)"), - amount: z.number().describe("The amount of the token to include in the gift card"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ token, amount, recvWindow }) => { - try { - const params: Record = { token, amount }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.createCode(params); + inputSchema: { + token: z.string().describe("The token to include in the gift card (e.g., BNB, USDT)"), + amount: z.number().describe("The amount of the token to include in the gift card"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ token, amount, recvWindow }) => { + try { + const params: Record = { token, amount }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.createCode(params); + + return { + content: [ + { + type: "text", + text: `Gift card code created successfully for ${amount} ${token}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Gift card code created successfully for ${amount} ${token}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create gift card code: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to create gift card code: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/createDualTokenCode.ts b/src/tools/binance-gift-card/createDualTokenCode.ts index 965e319f..443cc3b1 100644 --- a/src/tools/binance-gift-card/createDualTokenCode.ts +++ b/src/tools/binance-gift-card/createDualTokenCode.ts @@ -1,44 +1,52 @@ // src/tools/binance-gift-card/createDualTokenCode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardCreateDualTokenCode(server: McpServer) { - server.tool( - "BinanceGiftCardCreateDualTokenCode", + server.registerTool( + "BinanceGiftCardCreateDualTokenCode", + { + description: "Create a dual-token Binance Gift Card. This creates a gift card where the base token is exchanged to the face token for redemption.", - { - baseToken: z.string().describe("The token used as the base for the gift card (token you pay with)"), - faceToken: z.string().describe("The token the recipient will receive when redeeming"), - baseTokenAmount: z.number().describe("The amount of base token to convert"), - discount: z.number().optional().describe("Discount percentage (if applicable)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ baseToken, faceToken, baseTokenAmount, discount, recvWindow }) => { - try { - const params: Record = { baseToken, faceToken, baseTokenAmount }; - if (discount !== undefined) params.discount = discount; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.createDualTokenCode(params); + inputSchema: { + baseToken: z + .string() + .describe("The token used as the base for the gift card (token you pay with)"), + faceToken: z.string().describe("The token the recipient will receive when redeeming"), + baseTokenAmount: z.number().describe("The amount of base token to convert"), + discount: z.number().optional().describe("Discount percentage (if applicable)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ baseToken, faceToken, baseTokenAmount, discount, recvWindow }) => { + try { + const params: Record = { baseToken, faceToken, baseTokenAmount }; + if (discount !== undefined) params.discount = discount; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.createDualTokenCode(params); + + return { + content: [ + { + type: "text", + text: `Dual-token gift card created: ${baseTokenAmount} ${baseToken} -> ${faceToken}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Dual-token gift card created: ${baseTokenAmount} ${baseToken} -> ${faceToken}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create dual-token gift card: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create dual-token gift card: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/createDualTokenGiftCard.ts b/src/tools/binance-gift-card/createDualTokenGiftCard.ts index add352b5..b865e399 100644 --- a/src/tools/binance-gift-card/createDualTokenGiftCard.ts +++ b/src/tools/binance-gift-card/createDualTokenGiftCard.ts @@ -5,46 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/createDualTokenGiftCard.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardCreateDualToken(server: McpServer) { - server.tool( - "BinanceGiftCardCreateDualToken", + server.registerTool( + "BinanceGiftCardCreateDualToken", + { + description: "Create a dual-token Binance Gift Card. Allows creating a gift card using one token that the recipient will receive as another token.", - { - baseToken: z.string().describe("Token used to pay for the gift card (e.g., 'USDT')"), - faceToken: z.string().describe("Token that the recipient will receive (e.g., 'BNB')"), - baseTokenAmount: z.string().describe("Amount of base token to spend"), - discount: z.number().optional().describe("Discount rate (0-100)"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.createDualTokenCode({ - baseToken: params.baseToken, - faceToken: params.faceToken, - baseTokenAmount: params.baseTokenAmount, - ...(params.discount !== undefined && { discount: params.discount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Dual-Token Gift Card Created!\n\nReference No: ${data.referenceNo}\nCode: ${data.code}\nPaid: ${params.baseTokenAmount} ${params.baseToken}\nRecipient Gets: ${data.faceTokenAmount || 'N/A'} ${params.faceToken}\n\n⚠️ Keep the code secure!` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to create dual-token gift card: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + baseToken: z.string().describe("Token used to pay for the gift card (e.g., 'USDT')"), + faceToken: z.string().describe("Token that the recipient will receive (e.g., 'BNB')"), + baseTokenAmount: z.string().describe("Amount of base token to spend"), + discount: z.number().optional().describe("Discount rate (0-100)"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.createDualTokenCode({ + baseToken: params.baseToken, + faceToken: params.faceToken, + baseTokenAmount: params.baseTokenAmount, + ...(params.discount !== undefined && { discount: params.discount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Dual-Token Gift Card Created!\n\nReference No: ${data.referenceNo}\nCode: ${data.code}\nPaid: ${params.baseTokenAmount} ${params.baseToken}\nRecipient Gets: ${data.faceTokenAmount || "N/A"} ${params.faceToken}\n\n⚠️ Keep the code secure!`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to create dual-token gift card: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/createGiftCard.ts b/src/tools/binance-gift-card/createGiftCard.ts index 63799d0b..a0be0c43 100644 --- a/src/tools/binance-gift-card/createGiftCard.ts +++ b/src/tools/binance-gift-card/createGiftCard.ts @@ -5,42 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/createGiftCard.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardCreate(server: McpServer) { - server.tool( - "BinanceGiftCardCreate", + server.registerTool( + "BinanceGiftCardCreate", + { + description: "Create a Binance Gift Card. The card will be deducted from your spot wallet balance.", - { - token: z.string().describe("Token type (e.g., 'BNB', 'USDT', 'BTC')"), - amount: z.string().describe("Amount of tokens to include in gift card"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.createCode({ - token: params.token, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Gift Card Created!\n\nReference No: ${data.referenceNo}\nCode: ${data.code}\nToken: ${params.token}\nAmount: ${params.amount}\n\n⚠️ Keep the code secure! Anyone with the code can redeem it.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to create gift card: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + token: z.string().describe("Token type (e.g., 'BNB', 'USDT', 'BTC')"), + amount: z.string().describe("Amount of tokens to include in gift card"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.createCode({ + token: params.token, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Gift Card Created!\n\nReference No: ${data.referenceNo}\nCode: ${data.code}\nToken: ${params.token}\nAmount: ${params.amount}\n\n⚠️ Keep the code secure! Anyone with the code can redeem it.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to create gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/getTokenLimit.ts b/src/tools/binance-gift-card/getTokenLimit.ts index da856247..5c8940a1 100644 --- a/src/tools/binance-gift-card/getTokenLimit.ts +++ b/src/tools/binance-gift-card/getTokenLimit.ts @@ -1,40 +1,44 @@ // src/tools/binance-gift-card/getTokenLimit.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardGetTokenLimit(server: McpServer) { - server.tool( - "BinanceGiftCardGetTokenLimit", + server.registerTool( + "BinanceGiftCardGetTokenLimit", + { + description: "Fetch the token limits for buying gift cards, including minimum and maximum amounts.", - { - baseToken: z.string().describe("The base token to check limits for (e.g., USDT)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ baseToken, recvWindow }) => { - try { - const params: Record = { baseToken }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.getTokenLimit(params); + inputSchema: { + baseToken: z.string().describe("The base token to check limits for (e.g., USDT)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ baseToken, recvWindow }) => { + try { + const params: Record = { baseToken }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.getTokenLimit(params); + + return { + content: [ + { + type: "text", + text: `Token limit for ${baseToken}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Token limit for ${baseToken}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to fetch token limit: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to fetch token limit: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/index.ts b/src/tools/binance-gift-card/index.ts index 2f3dbdf0..48f11655 100644 --- a/src/tools/binance-gift-card/index.ts +++ b/src/tools/binance-gift-card/index.ts @@ -1,24 +1,25 @@ // src/tools/binance-gift-card/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceGiftCardBuyCode } from "./buyCode.js"; import { registerBinanceGiftCardCreateCode } from "./createCode.js"; import { registerBinanceGiftCardCreateDualTokenCode } from "./createDualTokenCode.js"; +import { registerBinanceGiftCardGetTokenLimit } from "./getTokenLimit.js"; import { registerBinanceGiftCardRedeemCode } from "./redeemCode.js"; -import { registerBinanceGiftCardVerify } from "./verify.js"; import { registerBinanceGiftCardRsaPublicKey } from "./rsaPublicKey.js"; -import { registerBinanceGiftCardBuyCode } from "./buyCode.js"; -import { registerBinanceGiftCardGetTokenLimit } from "./getTokenLimit.js"; +import { registerBinanceGiftCardVerify } from "./verify.js"; export function registerBinanceGiftCardTools(server: McpServer) { - // Create Gift Cards - registerBinanceGiftCardCreateCode(server); - registerBinanceGiftCardCreateDualTokenCode(server); - registerBinanceGiftCardBuyCode(server); - - // Redeem & Verify - registerBinanceGiftCardRedeemCode(server); - registerBinanceGiftCardVerify(server); - - // Utilities - registerBinanceGiftCardRsaPublicKey(server); - registerBinanceGiftCardGetTokenLimit(server); + // Create Gift Cards + registerBinanceGiftCardCreateCode(server); + registerBinanceGiftCardCreateDualTokenCode(server); + registerBinanceGiftCardBuyCode(server); + + // Redeem & Verify + registerBinanceGiftCardRedeemCode(server); + registerBinanceGiftCardVerify(server); + + // Utilities + registerBinanceGiftCardRsaPublicKey(server); + registerBinanceGiftCardGetTokenLimit(server); } diff --git a/src/tools/binance-gift-card/redeemCode.ts b/src/tools/binance-gift-card/redeemCode.ts index 9cb054c9..c4b630ea 100644 --- a/src/tools/binance-gift-card/redeemCode.ts +++ b/src/tools/binance-gift-card/redeemCode.ts @@ -1,42 +1,48 @@ // src/tools/binance-gift-card/redeemCode.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardRedeemCode(server: McpServer) { - server.tool( - "BinanceGiftCardRedeemCode", - "Redeem a Binance Gift Card code. The tokens will be credited to your account.", - { - code: z.string().describe("The gift card code to redeem"), - externalUid: z.string().optional().describe("External unique identifier for the redemption"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ code, externalUid, recvWindow }) => { - try { - const params: Record = { code }; - if (externalUid !== undefined) params.externalUid = externalUid; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.redeemCode(params); + server.registerTool( + "BinanceGiftCardRedeemCode", + { + description: "Redeem a Binance Gift Card code. The tokens will be credited to your account.", + inputSchema: { + code: z.string().describe("The gift card code to redeem"), + externalUid: z + .string() + .optional() + .describe("External unique identifier for the redemption"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ code, externalUid, recvWindow }) => { + try { + const params: Record = { code }; + if (externalUid !== undefined) params.externalUid = externalUid; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.redeemCode(params); + + return { + content: [ + { + type: "text", + text: `Gift card redeemed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Gift card redeemed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to redeem gift card: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to redeem gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/redeemDualTokenGiftCard.ts b/src/tools/binance-gift-card/redeemDualTokenGiftCard.ts index 72cf9ecb..28c9c4da 100644 --- a/src/tools/binance-gift-card/redeemDualTokenGiftCard.ts +++ b/src/tools/binance-gift-card/redeemDualTokenGiftCard.ts @@ -5,42 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/redeemDualTokenGiftCard.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardRedeemDualToken(server: McpServer) { - server.tool( - "BinanceGiftCardRedeemDualToken", - "Redeem a dual-token Binance Gift Card.", - { - code: z.string().describe("Gift card redemption code"), - externalUid: z.string().optional().describe("External user ID for partner integration"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.redeemDualTokenCode({ - code: params.code, - ...(params.externalUid && { externalUid: params.externalUid }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Dual-Token Gift Card Redeemed!\n\nReference No: ${data.referenceNo}\nToken Received: ${data.token}\nAmount: ${data.amount}\n\nTokens have been credited to your spot wallet.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to redeem dual-token gift card: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceGiftCardRedeemDualToken", + { + description: "Redeem a dual-token Binance Gift Card.", + inputSchema: { + code: z.string().describe("Gift card redemption code"), + externalUid: z.string().optional().describe("External user ID for partner integration"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.redeemDualTokenCode({ + code: params.code, + ...(params.externalUid && { externalUid: params.externalUid }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Dual-Token Gift Card Redeemed!\n\nReference No: ${data.referenceNo}\nToken Received: ${data.token}\nAmount: ${data.amount}\n\nTokens have been credited to your spot wallet.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `❌ Failed to redeem dual-token gift card: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/redeemGiftCard.ts b/src/tools/binance-gift-card/redeemGiftCard.ts index d70937ef..101e3770 100644 --- a/src/tools/binance-gift-card/redeemGiftCard.ts +++ b/src/tools/binance-gift-card/redeemGiftCard.ts @@ -5,42 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/redeemGiftCard.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardRedeem(server: McpServer) { - server.tool( - "BinanceGiftCardRedeem", - "Redeem a Binance Gift Card. The tokens will be credited to your spot wallet.", - { - code: z.string().describe("Gift card redemption code"), - externalUid: z.string().optional().describe("External user ID for partner integration"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.redeemCode({ - code: params.code, - ...(params.externalUid && { externalUid: params.externalUid }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `✅ Gift Card Redeemed!\n\nReference No: ${data.referenceNo}\nToken: ${data.token}\nAmount: ${data.amount}\n\nTokens have been credited to your spot wallet.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to redeem gift card: ${errorMessage}` }], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceGiftCardRedeem", + { + description: "Redeem a Binance Gift Card. The tokens will be credited to your spot wallet.", + inputSchema: { + code: z.string().describe("Gift card redemption code"), + externalUid: z.string().optional().describe("External user ID for partner integration"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.redeemCode({ + code: params.code, + ...(params.externalUid && { externalUid: params.externalUid }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `✅ Gift Card Redeemed!\n\nReference No: ${data.referenceNo}\nToken: ${data.token}\nAmount: ${data.amount}\n\nTokens have been credited to your spot wallet.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to redeem gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/rsaPublicKey.ts b/src/tools/binance-gift-card/rsaPublicKey.ts index 13133b39..2f4f3505 100644 --- a/src/tools/binance-gift-card/rsaPublicKey.ts +++ b/src/tools/binance-gift-card/rsaPublicKey.ts @@ -1,39 +1,42 @@ // src/tools/binance-gift-card/rsaPublicKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardRsaPublicKey(server: McpServer) { - server.tool( - "BinanceGiftCardRsaPublicKey", - "Fetch the RSA public key for encrypting gift card codes.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.rsaPublicKey(params); + server.registerTool( + "BinanceGiftCardRsaPublicKey", + { + description: "Fetch the RSA public key for encrypting gift card codes.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.rsaPublicKey(params); + + return { + content: [ + { + type: "text", + text: `Retrieved RSA public key. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved RSA public key. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to fetch RSA public key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to fetch RSA public key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/tokenLimit.ts b/src/tools/binance-gift-card/tokenLimit.ts index 9e94f07b..bc860cf8 100644 --- a/src/tools/binance-gift-card/tokenLimit.ts +++ b/src/tools/binance-gift-card/tokenLimit.ts @@ -5,40 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/tokenLimit.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardTokenLimit(server: McpServer) { - server.tool( - "BinanceGiftCardTokenLimit", + server.registerTool( + "BinanceGiftCardTokenLimit", + { + description: "Get token limit information for Binance Gift Card creation. Shows minimum and maximum amounts.", - { - baseToken: z.string().describe("Base token for buying gift cards (e.g., 'USDT')"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.tokenLimit({ - baseToken: params.baseToken, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - return { - content: [{ - type: "text", - text: `📊 Gift Card Token Limits for ${params.baseToken}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get token limits: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + baseToken: z.string().describe("Base token for buying gift cards (e.g., 'USDT')"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.tokenLimit({ + baseToken: params.baseToken, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `📊 Gift Card Token Limits for ${params.baseToken}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to get token limits: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/verify.ts b/src/tools/binance-gift-card/verify.ts index 0282cf5e..76a71925 100644 --- a/src/tools/binance-gift-card/verify.ts +++ b/src/tools/binance-gift-card/verify.ts @@ -1,40 +1,44 @@ // src/tools/binance-gift-card/verify.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { giftCardClient } from "../../config/binanceClient.js"; export function registerBinanceGiftCardVerify(server: McpServer) { - server.tool( - "BinanceGiftCardVerify", + server.registerTool( + "BinanceGiftCardVerify", + { + description: "Verify a Binance Gift Card code to check its validity and status without redeeming it.", - { - referenceNo: z.string().describe("The reference number of the gift card to verify"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ referenceNo, recvWindow }) => { - try { - const params: Record = { referenceNo }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await giftCardClient.verify(params); + inputSchema: { + referenceNo: z.string().describe("The reference number of the gift card to verify"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ referenceNo, recvWindow }) => { + try { + const params: Record = { referenceNo }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await giftCardClient.verify(params); + + return { + content: [ + { + type: "text", + text: `Gift card verification result. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Gift card verification result. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to verify gift card: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to verify gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-gift-card/verifyGiftCard.ts b/src/tools/binance-gift-card/verifyGiftCard.ts index fc580174..61f4a009 100644 --- a/src/tools/binance-gift-card/verifyGiftCard.ts +++ b/src/tools/binance-gift-card/verifyGiftCard.ts @@ -5,44 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-gift-card/verifyGiftCard.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { giftCardClient } from "../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { giftCardClient } from "../../config/binanceClient.js"; + export function registerBinanceGiftCardVerify(server: McpServer) { - server.tool( - "BinanceGiftCardVerify", + server.registerTool( + "BinanceGiftCardVerify", + { + description: "Verify a Binance Gift Card code. Check if the code is valid and see its details before redeeming.", - { - referenceNo: z.string().describe("Gift card reference number"), - recvWindow: z.number().int().optional().describe("Request validity window in ms") - }, - async (params) => { - try { - const response = await giftCardClient.restAPI.verify({ - referenceNo: params.referenceNo, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const data = await response.data(); - - let statusText = "Unknown"; - if (data.valid === true) statusText = "✅ Valid"; - else if (data.valid === false) statusText = "❌ Invalid/Used"; - - return { - content: [{ - type: "text", - text: `🎁 Gift Card Verification\n\nReference No: ${params.referenceNo}\nStatus: ${statusText}\nToken: ${data.token || 'N/A'}\nAmount: ${data.amount || 'N/A'}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to verify gift card: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + referenceNo: z.string().describe("Gift card reference number"), + recvWindow: z.number().int().optional().describe("Request validity window in ms"), + }, + }, + async (params) => { + try { + const response = await giftCardClient.restAPI.verify({ + referenceNo: params.referenceNo, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + let statusText = "Unknown"; + if (data.valid === true) statusText = "✅ Valid"; + else if (data.valid === false) statusText = "❌ Invalid/Used"; + + return { + content: [ + { + type: "text", + text: `🎁 Gift Card Verification\n\nReference No: ${params.referenceNo}\nStatus: ${statusText}\nToken: ${data.token || "N/A"}\nAmount: ${data.amount || "N/A"}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `❌ Failed to verify gift card: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginAccount.ts b/src/tools/binance-margin/cross-margin-api/crossMarginAccount.ts index 366bc51e..eeb5bffa 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginAccount.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginAccount.ts @@ -1,34 +1,42 @@ // src/tools/binance-margin/cross-margin-api/crossMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginAccount(server: McpServer) { - server.tool( - "BinanceCrossMarginAccount", + server.registerTool( + "BinanceCrossMarginAccount", + { + description: "Query Cross Margin account details including balances, margin level, and collateral info.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin Account Details: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin Account Details: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query account: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginAllAssets.ts b/src/tools/binance-margin/cross-margin-api/crossMarginAllAssets.ts index 91faa575..625115ef 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginAllAssets.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginAllAssets.ts @@ -5,47 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-margin/cross-margin-api/crossMarginAllAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginAllAssets(server: McpServer) { - server.tool( - "BinanceCrossMarginAllAssets", + server.registerTool( + "BinanceCrossMarginAllAssets", + { + description: "Get all assets available for cross margin trading, including borrowable status, daily interest rates, and limits.", - { - asset: z.string().optional().describe("Specific asset to query (e.g., BTC, USDT). If not provided, returns all assets."), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.getAllCrossMarginPairs({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z + .string() + .optional() + .describe( + "Specific asset to query (e.g., BTC, USDT). If not provided, returns all assets.", + ), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.getAllCrossMarginPairs({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); - const data = await response.data(); - - // If specific asset requested, filter results - let result = data; - if (params.asset && Array.isArray(data)) { - result = data.filter((item: any) => - item.base === params.asset || item.quote === params.asset - ); - } + const data = await response.data(); - return { - content: [{ - type: "text", - text: `Cross Margin Assets: ${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query cross margin assets: ${errorMessage}` }], - isError: true - }; - } + // If specific asset requested, filter results + let result = data; + if (params.asset && Array.isArray(data)) { + result = data.filter( + (item: any) => item.base === params.asset || item.quote === params.asset, + ); } - ); + + return { + content: [ + { + type: "text", + text: `Cross Margin Assets: ${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to query cross margin assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginAllOrders.ts b/src/tools/binance-margin/cross-margin-api/crossMarginAllOrders.ts index 31fe94d4..5b3561a9 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginAllOrders.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginAllOrders.ts @@ -1,46 +1,54 @@ // src/tools/binance-margin/cross-margin-api/crossMarginAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginAllOrders(server: McpServer) { - server.tool( - "BinanceCrossMarginAllOrders", + server.registerTool( + "BinanceCrossMarginAllOrders", + { + description: "Query all margin orders for a symbol. Returns both open and filled/cancelled orders.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAllOrders({ - symbol: params.symbol, - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAllOrders({ + symbol: params.symbol, + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `All Margin Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `All Margin Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginAvailableInventory.ts b/src/tools/binance-margin/cross-margin-api/crossMarginAvailableInventory.ts index e4daf4b4..1253a8f6 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginAvailableInventory.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginAvailableInventory.ts @@ -1,36 +1,45 @@ // src/tools/binance-margin/cross-margin-api/crossMarginAvailableInventory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginAvailableInventory(server: McpServer) { - server.tool( - "BinanceCrossMarginAvailableInventory", - "Query margin available inventory for borrowing.", - { - type: z.enum(["MARGIN", "ISOLATED"]).describe("Type of margin (MARGIN for cross, ISOLATED for isolated)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAvailableInventory({ - type: params.type, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginAvailableInventory", + { + description: "Query margin available inventory for borrowing.", + inputSchema: { + type: z + .enum(["MARGIN", "ISOLATED"]) + .describe("Type of margin (MARGIN for cross, ISOLATED for isolated)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAvailableInventory({ + type: params.type, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Margin Available Inventory: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin Available Inventory: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query available inventory: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query available inventory: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginBorrow.ts b/src/tools/binance-margin/cross-margin-api/crossMarginBorrow.ts index c991330e..dfcc3a36 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginBorrow.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginBorrow.ts @@ -1,42 +1,53 @@ // src/tools/binance-margin/cross-margin-api/crossMarginBorrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginBorrow(server: McpServer) { - server.tool( - "BinanceCrossMarginBorrow", + server.registerTool( + "BinanceCrossMarginBorrow", + { + description: "Borrow assets in Cross Margin account. Apply for a loan with the specified asset and amount.", - { - asset: z.string().describe("Asset to borrow (e.g., BTC, USDT)"), - amount: z.string().describe("Amount to borrow"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not, default FALSE"), - symbol: z.string().optional().describe("Isolated symbol, required when isIsolated=TRUE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.borrow({ - asset: params.asset, - amount: params.amount, - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().describe("Asset to borrow (e.g., BTC, USDT)"), + amount: z.string().describe("Amount to borrow"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin or not, default FALSE"), + symbol: z.string().optional().describe("Isolated symbol, required when isIsolated=TRUE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.borrow({ + asset: params.asset, + amount: params.amount, + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully borrowed ${params.amount} ${params.asset} in Cross Margin. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Successfully borrowed ${params.amount} ${params.asset} in Cross Margin. Response: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to borrow: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to borrow: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginCancelAllOrders.ts b/src/tools/binance-margin/cross-margin-api/crossMarginCancelAllOrders.ts index 06f1ce00..d9ec609f 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginCancelAllOrders.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginCancelAllOrders.ts @@ -1,36 +1,44 @@ // src/tools/binance-margin/cross-margin-api/crossMarginCancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginCancelAllOrders(server: McpServer) { - server.tool( - "BinanceCrossMarginCancelAllOrders", + server.registerTool( + "BinanceCrossMarginCancelAllOrders", + { + description: "Cancel all open margin orders for a specific trading pair. This will cancel all open orders on the symbol.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.cancelAllOpenOrders({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.cancelAllOpenOrders({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `All open margin orders cancelled for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `All open margin orders cancelled for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to cancel all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginCancelOrder.ts b/src/tools/binance-margin/cross-margin-api/crossMarginCancelOrder.ts index b8f29a00..763f0724 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginCancelOrder.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginCancelOrder.ts @@ -1,42 +1,53 @@ // src/tools/binance-margin/cross-margin-api/crossMarginCancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginCancelOrder(server: McpServer) { - server.tool( - "BinanceCrossMarginCancelOrder", + server.registerTool( + "BinanceCrossMarginCancelOrder", + { + description: "Cancel an active margin order. Either orderId or origClientOrderId must be provided.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - newClientOrderId: z.string().optional().describe("New client order ID for the cancel request"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.cancelOrder({ - symbol: params.symbol, - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for the cancel request"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.cancelOrder({ + symbol: params.symbol, + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Margin order cancelled successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin order cancelled successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel margin order: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to cancel margin order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginCapitalFlow.ts b/src/tools/binance-margin/cross-margin-api/crossMarginCapitalFlow.ts index 8bcde944..07280173 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginCapitalFlow.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginCapitalFlow.ts @@ -1,48 +1,71 @@ // src/tools/binance-margin/cross-margin-api/crossMarginCapitalFlow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginCapitalFlow(server: McpServer) { - server.tool( - "BinanceCrossMarginCapitalFlow", + server.registerTool( + "BinanceCrossMarginCapitalFlow", + { + description: "Get cross margin capital flow history including transfers, borrows, repays, and interest.", - { - asset: z.string().optional().describe("Filter by asset symbol"), - symbol: z.string().optional().describe("Filter by trading pair symbol"), - type: z.enum(["TRANSFER_IN", "TRANSFER_OUT", "BORROW", "REPAY", "BUY_INCOME", "SELL_LOSS", "TRADING_COMMISSION", "LIQUIDATION", "INTEREST", "SMALL_LIABILITY_EXCHANGE", "SMALL_ASSETS_EXCHANGE"]).optional().describe("Type of capital flow"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Start from ID"), - limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getCapitalFlow({ - ...(params.asset && { asset: params.asset }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.type && { type: params.type }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by asset symbol"), + symbol: z.string().optional().describe("Filter by trading pair symbol"), + type: z + .enum([ + "TRANSFER_IN", + "TRANSFER_OUT", + "BORROW", + "REPAY", + "BUY_INCOME", + "SELL_LOSS", + "TRADING_COMMISSION", + "LIQUIDATION", + "INTEREST", + "SMALL_LIABILITY_EXCHANGE", + "SMALL_ASSETS_EXCHANGE", + ]) + .optional() + .describe("Type of capital flow"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Start from ID"), + limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getCapitalFlow({ + ...(params.asset && { asset: params.asset }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.type && { type: params.type }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin Capital Flow: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin Capital Flow: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get capital flow: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get capital flow: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginDelist.ts b/src/tools/binance-margin/cross-margin-api/crossMarginDelist.ts index 34f9bf50..6ae78f3f 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginDelist.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginDelist.ts @@ -1,34 +1,41 @@ // src/tools/binance-margin/cross-margin-api/crossMarginDelist.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginDelist(server: McpServer) { - server.tool( - "BinanceCrossMarginDelist", - "Get delist schedule for cross margin trading pairs. Shows upcoming delistings.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getDelistSchedule({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginDelist", + { + description: "Get delist schedule for cross margin trading pairs. Shows upcoming delistings.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getDelistSchedule({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin Delist Schedule: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin Delist Schedule: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get delist schedule: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get delist schedule: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginDustLog.ts b/src/tools/binance-margin/cross-margin-api/crossMarginDustLog.ts index 6460c28e..31aa0e03 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginDustLog.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginDustLog.ts @@ -1,38 +1,46 @@ // src/tools/binance-margin/cross-margin-api/crossMarginDustLog.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginDustLog(server: McpServer) { - server.tool( - "BinanceCrossMarginDustLog", + server.registerTool( + "BinanceCrossMarginDustLog", + { + description: "Query margin dust conversion log. Shows history of small balance conversions to BNB.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getDustLog({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getDustLog({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Margin Dust Log: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin Dust Log: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query dust log: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query dust log: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginFee.ts b/src/tools/binance-margin/cross-margin-api/crossMarginFee.ts index 783b9ad2..9d0e4441 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginFee.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginFee.ts @@ -1,38 +1,50 @@ // src/tools/binance-margin/cross-margin-api/crossMarginFee.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginFee(server: McpServer) { - server.tool( - "BinanceCrossMarginFee", + server.registerTool( + "BinanceCrossMarginFee", + { + description: "Query cross margin fee data including interest rates and collateral ratios for margin pairs.", - { - vipLevel: z.number().int().optional().describe("VIP level (default uses current account VIP level)"), - coin: z.string().optional().describe("Filter by specific coin"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getCrossMarginFee({ - ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), - ...(params.coin && { coin: params.coin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + vipLevel: z + .number() + .int() + .optional() + .describe("VIP level (default uses current account VIP level)"), + coin: z.string().optional().describe("Filter by specific coin"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getCrossMarginFee({ + ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), + ...(params.coin && { coin: params.coin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin Fee Data: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin Fee Data: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query cross margin fee: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query cross margin fee: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginForceLiquidationRec.ts b/src/tools/binance-margin/cross-margin-api/crossMarginForceLiquidationRec.ts index 66a178b4..55113bd5 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginForceLiquidationRec.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginForceLiquidationRec.ts @@ -1,44 +1,52 @@ // src/tools/binance-margin/cross-margin-api/crossMarginForceLiquidationRec.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginForceLiquidationRec(server: McpServer) { - server.tool( - "BinanceCrossMarginForceLiquidationRec", + server.registerTool( + "BinanceCrossMarginForceLiquidationRec", + { + description: "Get force liquidation record for margin account. Shows historical liquidation events.", - { - isolatedSymbol: z.string().optional().describe("Isolated symbol for isolated margin"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - current: z.number().int().optional().describe("Current page (default 1)"), - size: z.number().int().optional().describe("Page size (default 10, max 100)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getForceLiquidationRecord({ - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + isolatedSymbol: z.string().optional().describe("Isolated symbol for isolated margin"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + current: z.number().int().optional().describe("Current page (default 1)"), + size: z.number().int().optional().describe("Page size (default 10, max 100)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getForceLiquidationRecord({ + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Force Liquidation Records: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Force Liquidation Records: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get liquidation records: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get liquidation records: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginInterestHistory.ts b/src/tools/binance-margin/cross-margin-api/crossMarginInterestHistory.ts index ca834337..23887d38 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginInterestHistory.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginInterestHistory.ts @@ -1,48 +1,55 @@ // src/tools/binance-margin/cross-margin-api/crossMarginInterestHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginInterestHistory(server: McpServer) { - server.tool( - "BinanceCrossMarginInterestHistory", - "Query interest history for Cross Margin account.", - { - asset: z.string().optional().describe("Asset (e.g., BTC, USDT)"), - isolatedSymbol: z.string().optional().describe("Isolated symbol"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - current: z.number().int().optional().describe("Current page, default 1"), - size: z.number().int().optional().describe("Page size, default 10, max 100"), - archived: z.boolean().optional().describe("Query archived data, default false"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getInterestHistory({ - ...(params.asset && { asset: params.asset }), - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.archived !== undefined && { archived: params.archived }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginInterestHistory", + { + description: "Query interest history for Cross Margin account.", + inputSchema: { + asset: z.string().optional().describe("Asset (e.g., BTC, USDT)"), + isolatedSymbol: z.string().optional().describe("Isolated symbol"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().optional().describe("Current page, default 1"), + size: z.number().int().optional().describe("Page size, default 10, max 100"), + archived: z.boolean().optional().describe("Query archived data, default false"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getInterestHistory({ + ...(params.asset && { asset: params.asset }), + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.archived !== undefined && { archived: params.archived }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Interest History: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Interest History: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query interest history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query interest history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginInterestRateHistory.ts b/src/tools/binance-margin/cross-margin-api/crossMarginInterestRateHistory.ts index 9bec7ca5..8deb735a 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginInterestRateHistory.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginInterestRateHistory.ts @@ -1,42 +1,55 @@ // src/tools/binance-margin/cross-margin-api/crossMarginInterestRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginInterestRateHistory(server: McpServer) { - server.tool( - "BinanceCrossMarginInterestRateHistory", - "Query margin interest rate history for a specific asset.", - { - asset: z.string().describe("Asset symbol (e.g., BTC, USDT)"), - vipLevel: z.number().int().optional().describe("VIP level (default uses current account VIP level)"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getInterestRateHistory({ - asset: params.asset, - ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginInterestRateHistory", + { + description: "Query margin interest rate history for a specific asset.", + inputSchema: { + asset: z.string().describe("Asset symbol (e.g., BTC, USDT)"), + vipLevel: z + .number() + .int() + .optional() + .describe("VIP level (default uses current account VIP level)"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getInterestRateHistory({ + asset: params.asset, + ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Margin Interest Rate History for ${params.asset}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin Interest Rate History for ${params.asset}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query interest rate history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to query interest rate history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginLoanRecord.ts b/src/tools/binance-margin/cross-margin-api/crossMarginLoanRecord.ts index 55079602..1d27e87c 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginLoanRecord.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginLoanRecord.ts @@ -1,50 +1,57 @@ // src/tools/binance-margin/cross-margin-api/crossMarginLoanRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginLoanRecord(server: McpServer) { - server.tool( - "BinanceCrossMarginLoanRecord", - "Query loan record for Cross Margin account.", - { - asset: z.string().describe("Asset (e.g., BTC, USDT)"), - isolatedSymbol: z.string().optional().describe("Isolated symbol"), - txId: z.number().int().optional().describe("Transaction ID"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - current: z.number().int().optional().describe("Current page, default 1"), - size: z.number().int().optional().describe("Page size, default 10, max 100"), - archived: z.boolean().optional().describe("Query archived data, default false"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getLoanRecord({ - asset: params.asset, - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.txId && { txId: params.txId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.archived !== undefined && { archived: params.archived }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginLoanRecord", + { + description: "Query loan record for Cross Margin account.", + inputSchema: { + asset: z.string().describe("Asset (e.g., BTC, USDT)"), + isolatedSymbol: z.string().optional().describe("Isolated symbol"), + txId: z.number().int().optional().describe("Transaction ID"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().optional().describe("Current page, default 1"), + size: z.number().int().optional().describe("Page size, default 10, max 100"), + archived: z.boolean().optional().describe("Query archived data, default false"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getLoanRecord({ + asset: params.asset, + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.txId && { txId: params.txId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.archived !== undefined && { archived: params.archived }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Loan Records: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Loan Records: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query loan records: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query loan records: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginMaxBorrowable.ts b/src/tools/binance-margin/cross-margin-api/crossMarginMaxBorrowable.ts index 9c5c3fba..9ee7f4c6 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginMaxBorrowable.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginMaxBorrowable.ts @@ -1,38 +1,45 @@ // src/tools/binance-margin/cross-margin-api/crossMarginMaxBorrowable.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginMaxBorrowable(server: McpServer) { - server.tool( - "BinanceCrossMarginMaxBorrowable", - "Query maximum borrowable amount for an asset in Cross Margin.", - { - asset: z.string().describe("Asset (e.g., BTC, USDT)"), - isolatedSymbol: z.string().optional().describe("Isolated symbol"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getMaxBorrowable({ - asset: params.asset, - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginMaxBorrowable", + { + description: "Query maximum borrowable amount for an asset in Cross Margin.", + inputSchema: { + asset: z.string().describe("Asset (e.g., BTC, USDT)"), + isolatedSymbol: z.string().optional().describe("Isolated symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getMaxBorrowable({ + asset: params.asset, + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Max Borrowable for ${params.asset}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Max Borrowable for ${params.asset}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query max borrowable: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query max borrowable: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginMaxTransferable.ts b/src/tools/binance-margin/cross-margin-api/crossMarginMaxTransferable.ts index 240511f6..e1d3ef28 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginMaxTransferable.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginMaxTransferable.ts @@ -1,38 +1,45 @@ // src/tools/binance-margin/cross-margin-api/crossMarginMaxTransferable.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginMaxTransferable(server: McpServer) { - server.tool( - "BinanceCrossMarginMaxTransferable", - "Query maximum transferable amount for an asset in Cross Margin.", - { - asset: z.string().describe("Asset (e.g., BTC, USDT)"), - isolatedSymbol: z.string().optional().describe("Isolated symbol"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getMaxTransferable({ - asset: params.asset, - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginMaxTransferable", + { + description: "Query maximum transferable amount for an asset in Cross Margin.", + inputSchema: { + asset: z.string().describe("Asset (e.g., BTC, USDT)"), + isolatedSymbol: z.string().optional().describe("Isolated symbol"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getMaxTransferable({ + asset: params.asset, + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Max Transferable for ${params.asset}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Max Transferable for ${params.asset}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query max transferable: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query max transferable: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginMyTrades.ts b/src/tools/binance-margin/cross-margin-api/crossMarginMyTrades.ts index b59454fb..8b1d3f74 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginMyTrades.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginMyTrades.ts @@ -1,48 +1,55 @@ // src/tools/binance-margin/cross-margin-api/crossMarginMyTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginMyTrades(server: McpServer) { - server.tool( - "BinanceCrossMarginMyTrades", - "Query margin account trade history for a specific symbol.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), - orderId: z.number().int().optional().describe("Filter by order ID"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getMyTrades({ - symbol: params.symbol, - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginMyTrades", + { + description: "Query margin account trade history for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), + orderId: z.number().int().optional().describe("Filter by order ID"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getMyTrades({ + symbol: params.symbol, + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Margin Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginNewOrder.ts b/src/tools/binance-margin/cross-margin-api/crossMarginNewOrder.ts index 5cae320d..b1372bff 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginNewOrder.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginNewOrder.ts @@ -1,62 +1,96 @@ // src/tools/binance-margin/cross-margin-api/crossMarginNewOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginNewOrder(server: McpServer) { - server.tool( - "BinanceCrossMarginNewOrder", + server.registerTool( + "BinanceCrossMarginNewOrder", + { + description: "Post a new margin order in Cross Margin account. Supports various order types including LIMIT, MARKET, STOP_LOSS, etc.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]).describe("Order type"), - quantity: z.string().optional().describe("Order quantity"), - quoteOrderQty: z.string().optional().describe("Quote order quantity for MARKET orders"), - price: z.string().optional().describe("Order price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price for STOP_LOSS and TAKE_PROFIT orders"), - newClientOrderId: z.string().optional().describe("Unique client order ID"), - icebergQty: z.string().optional().describe("Iceberg quantity"), - newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), - sideEffectType: z.enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]).optional().describe("Side effect type for margin orders"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - selfTradePreventionMode: z.enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]).optional().describe("Self-trade prevention mode"), - autoRepayAtCancel: z.boolean().optional().describe("Auto repay at cancel, only for AUTO_BORROW_REPAY"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.newOrder({ - symbol: params.symbol, - side: params.side, - type: params.type, - ...(params.quantity && { quantity: params.quantity }), - ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.icebergQty && { icebergQty: params.icebergQty }), - ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), - ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.selfTradePreventionMode && { selfTradePreventionMode: params.selfTradePreventionMode }), - ...(params.autoRepayAtCancel !== undefined && { autoRepayAtCancel: params.autoRepayAtCancel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity"), + quoteOrderQty: z.string().optional().describe("Quote order quantity for MARKET orders"), + price: z.string().optional().describe("Order price (required for LIMIT orders)"), + stopPrice: z + .string() + .optional() + .describe("Stop price for STOP_LOSS and TAKE_PROFIT orders"), + newClientOrderId: z.string().optional().describe("Unique client order ID"), + icebergQty: z.string().optional().describe("Iceberg quantity"), + newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), + sideEffectType: z + .enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]) + .optional() + .describe("Side effect type for margin orders"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + selfTradePreventionMode: z + .enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]) + .optional() + .describe("Self-trade prevention mode"), + autoRepayAtCancel: z + .boolean() + .optional() + .describe("Auto repay at cancel, only for AUTO_BORROW_REPAY"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.newOrder({ + symbol: params.symbol, + side: params.side, + type: params.type, + ...(params.quantity && { quantity: params.quantity }), + ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.icebergQty && { icebergQty: params.icebergQty }), + ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), + ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.selfTradePreventionMode && { + selfTradePreventionMode: params.selfTradePreventionMode, + }), + ...(params.autoRepayAtCancel !== undefined && { + autoRepayAtCancel: params.autoRepayAtCancel, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin order placed successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin order placed successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place margin order: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to place margin order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginOpenOrders.ts b/src/tools/binance-margin/cross-margin-api/crossMarginOpenOrders.ts index 013947cb..20a398c0 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginOpenOrders.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginOpenOrders.ts @@ -1,38 +1,46 @@ // src/tools/binance-margin/cross-margin-api/crossMarginOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginOpenOrders(server: McpServer) { - server.tool( - "BinanceCrossMarginOpenOrders", + server.registerTool( + "BinanceCrossMarginOpenOrders", + { + description: "Query all open margin orders. If symbol is provided, only orders for that symbol are returned.", - { - symbol: z.string().optional().describe("Trading pair symbol (e.g., BTCUSDT)"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getOpenOrders({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol (e.g., BTCUSDT)"), + isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getOpenOrders({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Open Margin Orders: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Open Margin Orders: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginPairs.ts b/src/tools/binance-margin/cross-margin-api/crossMarginPairs.ts index 0e9133e5..9716b451 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginPairs.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginPairs.ts @@ -1,34 +1,42 @@ // src/tools/binance-margin/cross-margin-api/crossMarginPairs.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginPairs(server: McpServer) { - server.tool( - "BinanceCrossMarginPairs", + server.registerTool( + "BinanceCrossMarginPairs", + { + description: "Get all cross margin trading pairs. Returns information about all available cross margin pairs including base/quote assets and margin ratio.", - { - symbol: z.string().optional().describe("Filter by specific trading pair symbol") - }, - async (params) => { - try { - const data = await marginClient.getAllPairs({ - ...(params.symbol && { symbol: params.symbol }) - }); + inputSchema: { + symbol: z.string().optional().describe("Filter by specific trading pair symbol"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAllPairs({ + ...(params.symbol && { symbol: params.symbol }), + }); + + return { + content: [ + { + type: "text", + text: `Cross Margin Pairs: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Cross Margin Pairs: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get cross margin pairs: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get cross margin pairs: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginPriceIndex.ts b/src/tools/binance-margin/cross-margin-api/crossMarginPriceIndex.ts index e2452907..76434bcb 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginPriceIndex.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginPriceIndex.ts @@ -1,34 +1,42 @@ // src/tools/binance-margin/cross-margin-api/crossMarginPriceIndex.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginPriceIndex(server: McpServer) { - server.tool( - "BinanceCrossMarginPriceIndex", + server.registerTool( + "BinanceCrossMarginPriceIndex", + { + description: "Query margin price index for a specific trading pair. Returns the current price index used for margin calculations.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)") - }, - async (params) => { - try { - const data = await marginClient.getPriceIndex({ - symbol: params.symbol - }); + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), + }, + }, + async (params) => { + try { + const data = await marginClient.getPriceIndex({ + symbol: params.symbol, + }); + + return { + content: [ + { + type: "text", + text: `Margin Price Index for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Margin Price Index for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query price index: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query price index: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginRepay.ts b/src/tools/binance-margin/cross-margin-api/crossMarginRepay.ts index 2b0d3c97..1270b6ff 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginRepay.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginRepay.ts @@ -1,42 +1,53 @@ // src/tools/binance-margin/cross-margin-api/crossMarginRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginRepay(server: McpServer) { - server.tool( - "BinanceCrossMarginRepay", + server.registerTool( + "BinanceCrossMarginRepay", + { + description: "Repay loan for Cross Margin account. Repay the borrowed asset with the specified amount.", - { - asset: z.string().describe("Asset to repay (e.g., BTC, USDT)"), - amount: z.string().describe("Amount to repay"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin or not, default FALSE"), - symbol: z.string().optional().describe("Isolated symbol, required when isIsolated=TRUE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.repay({ - asset: params.asset, - amount: params.amount, - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().describe("Asset to repay (e.g., BTC, USDT)"), + amount: z.string().describe("Amount to repay"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin or not, default FALSE"), + symbol: z.string().optional().describe("Isolated symbol, required when isIsolated=TRUE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.repay({ + asset: params.asset, + amount: params.amount, + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully repaid ${params.amount} ${params.asset} in Cross Margin. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Successfully repaid ${params.amount} ${params.asset} in Cross Margin. Response: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to repay: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to repay: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginRepayRecord.ts b/src/tools/binance-margin/cross-margin-api/crossMarginRepayRecord.ts index 75e39f5a..1a66cf43 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginRepayRecord.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginRepayRecord.ts @@ -1,50 +1,57 @@ // src/tools/binance-margin/cross-margin-api/crossMarginRepayRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginRepayRecord(server: McpServer) { - server.tool( - "BinanceCrossMarginRepayRecord", - "Query repay record for Cross Margin account.", - { - asset: z.string().describe("Asset (e.g., BTC, USDT)"), - isolatedSymbol: z.string().optional().describe("Isolated symbol"), - txId: z.number().int().optional().describe("Transaction ID"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - current: z.number().int().optional().describe("Current page, default 1"), - size: z.number().int().optional().describe("Page size, default 10, max 100"), - archived: z.boolean().optional().describe("Query archived data, default false"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getRepayRecord({ - asset: params.asset, - ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), - ...(params.txId && { txId: params.txId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.archived !== undefined && { archived: params.archived }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginRepayRecord", + { + description: "Query repay record for Cross Margin account.", + inputSchema: { + asset: z.string().describe("Asset (e.g., BTC, USDT)"), + isolatedSymbol: z.string().optional().describe("Isolated symbol"), + txId: z.number().int().optional().describe("Transaction ID"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().optional().describe("Current page, default 1"), + size: z.number().int().optional().describe("Page size, default 10, max 100"), + archived: z.boolean().optional().describe("Query archived data, default false"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getRepayRecord({ + asset: params.asset, + ...(params.isolatedSymbol && { isolatedSymbol: params.isolatedSymbol }), + ...(params.txId && { txId: params.txId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.archived !== undefined && { archived: params.archived }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Repay Records: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Repay Records: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query repay records: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query repay records: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchange.ts b/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchange.ts index 25d8faac..5c1af40c 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchange.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchange.ts @@ -1,36 +1,46 @@ // src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchange.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginSmallLiabilityExchange(server: McpServer) { - server.tool( - "BinanceCrossMarginSmallLiabilityExchange", + server.registerTool( + "BinanceCrossMarginSmallLiabilityExchange", + { + description: "Cross margin small liability exchange. Converts small liabilities to a single asset.", - { - assetNames: z.array(z.string()).describe("Array of asset names to exchange (e.g., ['BTC', 'ETH'])"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.smallLiabilityExchange({ - assetNames: params.assetNames.join(","), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + assetNames: z + .array(z.string()) + .describe("Array of asset names to exchange (e.g., ['BTC', 'ETH'])"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.smallLiabilityExchange({ + assetNames: params.assetNames.join(","), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Small liability exchange completed: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Small liability exchange completed: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to exchange small liability: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to exchange small liability: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchangeHistory.ts b/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchangeHistory.ts index 1f680f73..bc202acd 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchangeHistory.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchangeHistory.ts @@ -1,42 +1,49 @@ // src/tools/binance-margin/cross-margin-api/crossMarginSmallLiabilityExchangeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginSmallLiabilityExchangeHistory(server: McpServer) { - server.tool( - "BinanceCrossMarginSmallLiabilityExchangeHistory", - "Get cross margin small liability exchange history.", - { - current: z.number().int().optional().describe("Current page (default 1)"), - size: z.number().int().optional().describe("Page size (default 10, max 100)"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getSmallLiabilityExchangeHistory({ - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceCrossMarginSmallLiabilityExchangeHistory", + { + description: "Get cross margin small liability exchange history.", + inputSchema: { + current: z.number().int().optional().describe("Current page (default 1)"), + size: z.number().int().optional().describe("Page size (default 10, max 100)"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getSmallLiabilityExchangeHistory({ + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Small Liability Exchange History: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Small Liability Exchange History: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get exchange history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get exchange history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/crossMarginTransfer.ts b/src/tools/binance-margin/cross-margin-api/crossMarginTransfer.ts index fe41def0..ed8f1829 100644 --- a/src/tools/binance-margin/cross-margin-api/crossMarginTransfer.ts +++ b/src/tools/binance-margin/cross-margin-api/crossMarginTransfer.ts @@ -1,40 +1,48 @@ // src/tools/binance-margin/cross-margin-api/crossMarginTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceCrossMarginTransfer(server: McpServer) { - server.tool( - "BinanceCrossMarginTransfer", + server.registerTool( + "BinanceCrossMarginTransfer", + { + description: "Execute a cross margin account transfer. Transfer between spot and cross margin accounts.", - { - asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), - amount: z.string().describe("Amount to transfer"), - type: z.enum(["1", "2"]).describe("1: Spot to Margin, 2: Margin to Spot"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.transfer({ - asset: params.asset, - amount: params.amount, - type: parseInt(params.type), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), + amount: z.string().describe("Amount to transfer"), + type: z.enum(["1", "2"]).describe("1: Spot to Margin, 2: Margin to Spot"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.transfer({ + asset: params.asset, + amount: params.amount, + type: parseInt(params.type), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully transferred ${params.amount} ${params.asset}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Successfully transferred ${params.amount} ${params.asset}. Response: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/cross-margin-api/index.ts b/src/tools/binance-margin/cross-margin-api/index.ts index ed39dd80..f968dc63 100644 --- a/src/tools/binance-margin/cross-margin-api/index.ts +++ b/src/tools/binance-margin/cross-margin-api/index.ts @@ -1,68 +1,69 @@ // src/tools/binance-margin/cross-margin-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceCrossMarginBorrow } from "./crossMarginBorrow.js"; -import { registerBinanceCrossMarginRepay } from "./crossMarginRepay.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCrossMarginAccount } from "./crossMarginAccount.js"; -import { registerBinanceCrossMarginTransfer } from "./crossMarginTransfer.js"; +import { registerBinanceCrossMarginAllOrders } from "./crossMarginAllOrders.js"; +import { registerBinanceCrossMarginAvailableInventory } from "./crossMarginAvailableInventory.js"; +import { registerBinanceCrossMarginBorrow } from "./crossMarginBorrow.js"; +import { registerBinanceCrossMarginCancelAllOrders } from "./crossMarginCancelAllOrders.js"; +import { registerBinanceCrossMarginCancelOrder } from "./crossMarginCancelOrder.js"; +import { registerBinanceCrossMarginCapitalFlow } from "./crossMarginCapitalFlow.js"; +import { registerBinanceCrossMarginDelist } from "./crossMarginDelist.js"; +import { registerBinanceCrossMarginDustLog } from "./crossMarginDustLog.js"; +import { registerBinanceCrossMarginFee } from "./crossMarginFee.js"; +import { registerBinanceCrossMarginForceLiquidationRec } from "./crossMarginForceLiquidationRec.js"; import { registerBinanceCrossMarginInterestHistory } from "./crossMarginInterestHistory.js"; +import { registerBinanceCrossMarginInterestRateHistory } from "./crossMarginInterestRateHistory.js"; import { registerBinanceCrossMarginLoanRecord } from "./crossMarginLoanRecord.js"; -import { registerBinanceCrossMarginRepayRecord } from "./crossMarginRepayRecord.js"; import { registerBinanceCrossMarginMaxBorrowable } from "./crossMarginMaxBorrowable.js"; import { registerBinanceCrossMarginMaxTransferable } from "./crossMarginMaxTransferable.js"; -import { registerBinanceCrossMarginPairs } from "./crossMarginPairs.js"; -import { registerBinanceCrossMarginPriceIndex } from "./crossMarginPriceIndex.js"; +import { registerBinanceCrossMarginMyTrades } from "./crossMarginMyTrades.js"; import { registerBinanceCrossMarginNewOrder } from "./crossMarginNewOrder.js"; -import { registerBinanceCrossMarginCancelOrder } from "./crossMarginCancelOrder.js"; -import { registerBinanceCrossMarginCancelAllOrders } from "./crossMarginCancelAllOrders.js"; import { registerBinanceCrossMarginOpenOrders } from "./crossMarginOpenOrders.js"; -import { registerBinanceCrossMarginAllOrders } from "./crossMarginAllOrders.js"; -import { registerBinanceCrossMarginMyTrades } from "./crossMarginMyTrades.js"; -import { registerBinanceCrossMarginForceLiquidationRec } from "./crossMarginForceLiquidationRec.js"; -import { registerBinanceCrossMarginInterestRateHistory } from "./crossMarginInterestRateHistory.js"; -import { registerBinanceCrossMarginFee } from "./crossMarginFee.js"; -import { registerBinanceCrossMarginDustLog } from "./crossMarginDustLog.js"; +import { registerBinanceCrossMarginPairs } from "./crossMarginPairs.js"; +import { registerBinanceCrossMarginPriceIndex } from "./crossMarginPriceIndex.js"; +import { registerBinanceCrossMarginRepay } from "./crossMarginRepay.js"; +import { registerBinanceCrossMarginRepayRecord } from "./crossMarginRepayRecord.js"; import { registerBinanceCrossMarginSmallLiabilityExchange } from "./crossMarginSmallLiabilityExchange.js"; import { registerBinanceCrossMarginSmallLiabilityExchangeHistory } from "./crossMarginSmallLiabilityExchangeHistory.js"; -import { registerBinanceCrossMarginAvailableInventory } from "./crossMarginAvailableInventory.js"; -import { registerBinanceCrossMarginCapitalFlow } from "./crossMarginCapitalFlow.js"; -import { registerBinanceCrossMarginDelist } from "./crossMarginDelist.js"; +import { registerBinanceCrossMarginTransfer } from "./crossMarginTransfer.js"; export function registerBinanceCrossMarginTools(server: McpServer) { - // Borrow & Repay - registerBinanceCrossMarginBorrow(server); - registerBinanceCrossMarginRepay(server); - - // Account & Transfer - registerBinanceCrossMarginAccount(server); - registerBinanceCrossMarginTransfer(server); - registerBinanceCrossMarginCapitalFlow(server); - - // Records & History - registerBinanceCrossMarginInterestHistory(server); - registerBinanceCrossMarginLoanRecord(server); - registerBinanceCrossMarginRepayRecord(server); - registerBinanceCrossMarginInterestRateHistory(server); - registerBinanceCrossMarginForceLiquidationRec(server); - - // Limits & Info - registerBinanceCrossMarginMaxBorrowable(server); - registerBinanceCrossMarginMaxTransferable(server); - registerBinanceCrossMarginPairs(server); - registerBinanceCrossMarginPriceIndex(server); - registerBinanceCrossMarginFee(server); - registerBinanceCrossMarginAvailableInventory(server); - registerBinanceCrossMarginDelist(server); - - // Trading - registerBinanceCrossMarginNewOrder(server); - registerBinanceCrossMarginCancelOrder(server); - registerBinanceCrossMarginCancelAllOrders(server); - registerBinanceCrossMarginOpenOrders(server); - registerBinanceCrossMarginAllOrders(server); - registerBinanceCrossMarginMyTrades(server); - - // Other - registerBinanceCrossMarginDustLog(server); - registerBinanceCrossMarginSmallLiabilityExchange(server); - registerBinanceCrossMarginSmallLiabilityExchangeHistory(server); + // Borrow & Repay + registerBinanceCrossMarginBorrow(server); + registerBinanceCrossMarginRepay(server); + + // Account & Transfer + registerBinanceCrossMarginAccount(server); + registerBinanceCrossMarginTransfer(server); + registerBinanceCrossMarginCapitalFlow(server); + + // Records & History + registerBinanceCrossMarginInterestHistory(server); + registerBinanceCrossMarginLoanRecord(server); + registerBinanceCrossMarginRepayRecord(server); + registerBinanceCrossMarginInterestRateHistory(server); + registerBinanceCrossMarginForceLiquidationRec(server); + + // Limits & Info + registerBinanceCrossMarginMaxBorrowable(server); + registerBinanceCrossMarginMaxTransferable(server); + registerBinanceCrossMarginPairs(server); + registerBinanceCrossMarginPriceIndex(server); + registerBinanceCrossMarginFee(server); + registerBinanceCrossMarginAvailableInventory(server); + registerBinanceCrossMarginDelist(server); + + // Trading + registerBinanceCrossMarginNewOrder(server); + registerBinanceCrossMarginCancelOrder(server); + registerBinanceCrossMarginCancelAllOrders(server); + registerBinanceCrossMarginOpenOrders(server); + registerBinanceCrossMarginAllOrders(server); + registerBinanceCrossMarginMyTrades(server); + + // Other + registerBinanceCrossMarginDustLog(server); + registerBinanceCrossMarginSmallLiabilityExchange(server); + registerBinanceCrossMarginSmallLiabilityExchangeHistory(server); } diff --git a/src/tools/binance-margin/index.ts b/src/tools/binance-margin/index.ts index d8d1164b..462e8a61 100644 --- a/src/tools/binance-margin/index.ts +++ b/src/tools/binance-margin/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-margin/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCrossMarginTools } from "./cross-margin-api/index.js"; import { registerBinanceIsolatedMarginTools } from "./isolated-margin-api/index.js"; export function registerBinanceMarginTools(server: McpServer) { - // Cross Margin API tools - registerBinanceCrossMarginTools(server); - - // Isolated Margin API tools - registerBinanceIsolatedMarginTools(server); + // Cross Margin API tools + registerBinanceCrossMarginTools(server); + + // Isolated Margin API tools + registerBinanceIsolatedMarginTools(server); } diff --git a/src/tools/binance-margin/isolated-margin-api/disableIsolatedMarginAccount.ts b/src/tools/binance-margin/isolated-margin-api/disableIsolatedMarginAccount.ts index aae1b2dd..f862c03e 100644 --- a/src/tools/binance-margin/isolated-margin-api/disableIsolatedMarginAccount.ts +++ b/src/tools/binance-margin/isolated-margin-api/disableIsolatedMarginAccount.ts @@ -5,39 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/disableIsolatedMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceDisableIsolatedMarginAccount(server: McpServer) { - server.tool( - "BinanceDisableIsolatedMarginAccount", + server.registerTool( + "BinanceDisableIsolatedMarginAccount", + { + description: "Disable isolated margin account for a specific symbol. All assets must be transferred out first.", - { - symbol: z.string().describe("Symbol to disable isolated margin for (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.disableIsolatedMarginAccount({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Symbol to disable isolated margin for (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.disableIsolatedMarginAccount({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Isolated margin account disabled for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Isolated margin account disabled for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to disable isolated margin: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to disable isolated margin: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/enableIsolatedMarginAccount.ts b/src/tools/binance-margin/isolated-margin-api/enableIsolatedMarginAccount.ts index fbe71060..4e36f773 100644 --- a/src/tools/binance-margin/isolated-margin-api/enableIsolatedMarginAccount.ts +++ b/src/tools/binance-margin/isolated-margin-api/enableIsolatedMarginAccount.ts @@ -5,39 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/enableIsolatedMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceEnableIsolatedMarginAccount(server: McpServer) { - server.tool( - "BinanceEnableIsolatedMarginAccount", - "Enable isolated margin account for a specific symbol.", - { - symbol: z.string().describe("Symbol to enable isolated margin for (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.enableIsolatedMarginAccount({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceEnableIsolatedMarginAccount", + { + description: "Enable isolated margin account for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Symbol to enable isolated margin for (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.enableIsolatedMarginAccount({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Isolated margin account enabled for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Isolated margin account enabled for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to enable isolated margin: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to enable isolated margin: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/getBnbBurnStatus.ts b/src/tools/binance-margin/isolated-margin-api/getBnbBurnStatus.ts index fff3a620..14302956 100644 --- a/src/tools/binance-margin/isolated-margin-api/getBnbBurnStatus.ts +++ b/src/tools/binance-margin/isolated-margin-api/getBnbBurnStatus.ts @@ -1,34 +1,41 @@ // src/tools/binance-margin/isolated-margin-api/getBnbBurnStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBnbBurnStatus(server: McpServer) { - server.tool( - "BinanceGetBnbBurnStatus", - "Get current BNB burn status for spot trading fees and margin interest.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceGetBnbBurnStatus", + { + description: "Get current BNB burn status for spot trading fees and margin interest.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `BNB Burn Status: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `BNB Burn Status: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get BNB burn status: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get BNB burn status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/index.ts b/src/tools/binance-margin/isolated-margin-api/index.ts index 815b5507..ee2459b1 100644 --- a/src/tools/binance-margin/isolated-margin-api/index.ts +++ b/src/tools/binance-margin/isolated-margin-api/index.ts @@ -1,42 +1,43 @@ // src/tools/binance-margin/isolated-margin-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceIsolatedMarginTransfer } from "./isolatedMarginTransfer.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceGetBnbBurnStatus } from "./getBnbBurnStatus.js"; import { registerBinanceIsolatedMarginAccount } from "./isolatedMarginAccount.js"; -import { registerBinanceIsolatedMarginPair } from "./isolatedMarginPair.js"; -import { registerBinanceIsolatedMarginAllPairs } from "./isolatedMarginAllPairs.js"; -import { registerBinanceIsolatedMarginTierData } from "./isolatedMarginTierData.js"; import { registerBinanceIsolatedMarginAccountLimit } from "./isolatedMarginAccountLimit.js"; +import { registerBinanceIsolatedMarginAllOrders } from "./isolatedMarginAllOrders.js"; +import { registerBinanceIsolatedMarginAllPairs } from "./isolatedMarginAllPairs.js"; +import { registerBinanceIsolatedMarginCancelOrder } from "./isolatedMarginCancelOrder.js"; import { registerBinanceIsolatedMarginFee } from "./isolatedMarginFee.js"; +import { registerBinanceIsolatedMarginMyTrades } from "./isolatedMarginMyTrades.js"; import { registerBinanceIsolatedMarginNewOrder } from "./isolatedMarginNewOrder.js"; -import { registerBinanceIsolatedMarginCancelOrder } from "./isolatedMarginCancelOrder.js"; import { registerBinanceIsolatedMarginOpenOrders } from "./isolatedMarginOpenOrders.js"; -import { registerBinanceIsolatedMarginAllOrders } from "./isolatedMarginAllOrders.js"; -import { registerBinanceIsolatedMarginMyTrades } from "./isolatedMarginMyTrades.js"; +import { registerBinanceIsolatedMarginPair } from "./isolatedMarginPair.js"; +import { registerBinanceIsolatedMarginTierData } from "./isolatedMarginTierData.js"; +import { registerBinanceIsolatedMarginTransfer } from "./isolatedMarginTransfer.js"; import { registerBinanceToggleBnbBurn } from "./toggleBnbBurn.js"; -import { registerBinanceGetBnbBurnStatus } from "./getBnbBurnStatus.js"; export function registerBinanceIsolatedMarginTools(server: McpServer) { - // Transfer - registerBinanceIsolatedMarginTransfer(server); - - // Account Info - registerBinanceIsolatedMarginAccount(server); - registerBinanceIsolatedMarginAccountLimit(server); - - // Pairs & Info - registerBinanceIsolatedMarginPair(server); - registerBinanceIsolatedMarginAllPairs(server); - registerBinanceIsolatedMarginTierData(server); - registerBinanceIsolatedMarginFee(server); - - // Trading - registerBinanceIsolatedMarginNewOrder(server); - registerBinanceIsolatedMarginCancelOrder(server); - registerBinanceIsolatedMarginOpenOrders(server); - registerBinanceIsolatedMarginAllOrders(server); - registerBinanceIsolatedMarginMyTrades(server); - - // BNB Burn - registerBinanceToggleBnbBurn(server); - registerBinanceGetBnbBurnStatus(server); + // Transfer + registerBinanceIsolatedMarginTransfer(server); + + // Account Info + registerBinanceIsolatedMarginAccount(server); + registerBinanceIsolatedMarginAccountLimit(server); + + // Pairs & Info + registerBinanceIsolatedMarginPair(server); + registerBinanceIsolatedMarginAllPairs(server); + registerBinanceIsolatedMarginTierData(server); + registerBinanceIsolatedMarginFee(server); + + // Trading + registerBinanceIsolatedMarginNewOrder(server); + registerBinanceIsolatedMarginCancelOrder(server); + registerBinanceIsolatedMarginOpenOrders(server); + registerBinanceIsolatedMarginAllOrders(server); + registerBinanceIsolatedMarginMyTrades(server); + + // BNB Burn + registerBinanceToggleBnbBurn(server); + registerBinanceGetBnbBurnStatus(server); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccount.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccount.ts index 0ec4ff14..079921c5 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccount.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccount.ts @@ -1,36 +1,47 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginAccount(server: McpServer) { - server.tool( - "BinanceIsolatedMarginAccount", + server.registerTool( + "BinanceIsolatedMarginAccount", + { + description: "Query isolated margin account info including balances, margin level, and liquidation price for all symbols or a specific symbol.", - { - symbols: z.string().optional().describe("Comma-separated symbol list (e.g., BTCUSDT,ETHUSDT), max 5 symbols"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedAccount({ - ...(params.symbols && { symbols: params.symbols }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbols: z + .string() + .optional() + .describe("Comma-separated symbol list (e.g., BTCUSDT,ETHUSDT), max 5 symbols"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedAccount({ + ...(params.symbols && { symbols: params.symbols }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Account Info: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Account Info: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query account: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccountLimit.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccountLimit.ts index c552b77c..d55ef173 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccountLimit.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAccountLimit.ts @@ -1,34 +1,42 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginAccountLimit.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginAccountLimit(server: McpServer) { - server.tool( - "BinanceIsolatedMarginAccountLimit", + server.registerTool( + "BinanceIsolatedMarginAccountLimit", + { + description: "Query the maximum number of isolated margin accounts allowed and currently enabled.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedAccount({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedAccount({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Account Limit: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Account Limit: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query account limit: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query account limit: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllOrders.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllOrders.ts index 282b533f..968b11e0 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllOrders.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllOrders.ts @@ -1,45 +1,53 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginAllOrders(server: McpServer) { - server.tool( - "BinanceIsolatedMarginAllOrders", + server.registerTool( + "BinanceIsolatedMarginAllOrders", + { + description: "Query all orders (open and filled/cancelled) in isolated margin account for a specific symbol.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID to start from"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAllOrders({ - symbol: params.symbol, - isIsolated: "TRUE", - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID to start from"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z.number().int().optional().describe("Number of results (default 500, max 500)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAllOrders({ + symbol: params.symbol, + isIsolated: "TRUE", + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `All Isolated Margin Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `All Isolated Margin Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query all orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllPairs.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllPairs.ts index 39a53a28..c304ed8b 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllPairs.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllPairs.ts @@ -1,34 +1,41 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginAllPairs.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginAllPairs(server: McpServer) { - server.tool( - "BinanceIsolatedMarginAllPairs", - "Get all isolated margin trading pairs with their information.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedMarginPairs({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginAllPairs", + { + description: "Get all isolated margin trading pairs with their information.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedMarginPairs({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `All Isolated Margin Pairs: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `All Isolated Margin Pairs: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get isolated pairs: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get isolated pairs: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllSymbols.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllSymbols.ts index dc47a10f..57751c39 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllSymbols.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginAllSymbols.ts @@ -5,37 +5,45 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/isolatedMarginAllSymbols.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginAllSymbols(server: McpServer) { - server.tool( - "BinanceIsolatedMarginAllSymbols", - "Query all isolated margin symbols available for trading.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.getAllIsolatedMarginSymbol({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginAllSymbols", + { + description: "Query all isolated margin symbols available for trading.", + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.getAllIsolatedMarginSymbol({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `All Isolated Margin Symbols: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `All Isolated Margin Symbols: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query all symbols: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query all symbols: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginBorrow.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginBorrow.ts index cd45cbd8..9fe794c3 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginBorrow.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginBorrow.ts @@ -5,45 +5,53 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/isolatedMarginBorrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginBorrow(server: McpServer) { - server.tool( - "BinanceIsolatedMarginBorrow", - "Borrow assets in isolated margin account for a specific symbol.", - { - asset: z.string().describe("Asset to borrow (e.g., BTC, USDT)"), - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - amount: z.string().describe("Amount to borrow"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.marginBorrowRepay({ - asset: params.asset, - isIsolated: "TRUE", - symbol: params.symbol, - amount: params.amount, - type: "BORROW", - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginBorrow", + { + description: "Borrow assets in isolated margin account for a specific symbol.", + inputSchema: { + asset: z.string().describe("Asset to borrow (e.g., BTC, USDT)"), + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + amount: z.string().describe("Amount to borrow"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.marginBorrowRepay({ + asset: params.asset, + isIsolated: "TRUE", + symbol: params.symbol, + amount: params.amount, + type: "BORROW", + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Borrowed ${params.amount} ${params.asset} for ${params.symbol}: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Borrowed ${params.amount} ${params.asset} for ${params.symbol}: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to borrow: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to borrow: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginCancelOrder.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginCancelOrder.ts index b6b23e1e..cdc2a505 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginCancelOrder.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginCancelOrder.ts @@ -1,43 +1,56 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginCancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginCancelOrder(server: McpServer) { - server.tool( - "BinanceIsolatedMarginCancelOrder", + server.registerTool( + "BinanceIsolatedMarginCancelOrder", + { + description: "Cancel an active isolated margin order. Either orderId or origClientOrderId must be provided.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - newClientOrderId: z.string().optional().describe("New client order ID for the cancel request"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.cancelOrder({ - symbol: params.symbol, - isIsolated: "TRUE", - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for the cancel request"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.cancelOrder({ + symbol: params.symbol, + isIsolated: "TRUE", + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated margin order cancelled successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated margin order cancelled successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel isolated margin order: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to cancel isolated margin order: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginFee.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginFee.ts index b6133c35..c00cee49 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginFee.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginFee.ts @@ -1,38 +1,49 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginFee.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginFee(server: McpServer) { - server.tool( - "BinanceIsolatedMarginFee", - "Query isolated margin fee data including interest rates for borrowing.", - { - symbol: z.string().optional().describe("Isolated margin symbol (e.g., BTCUSDT)"), - vipLevel: z.number().int().optional().describe("VIP level (default uses current account VIP level)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedMarginFee({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginFee", + { + description: "Query isolated margin fee data including interest rates for borrowing.", + inputSchema: { + symbol: z.string().optional().describe("Isolated margin symbol (e.g., BTCUSDT)"), + vipLevel: z + .number() + .int() + .optional() + .describe("VIP level (default uses current account VIP level)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedMarginFee({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.vipLevel !== undefined && { vipLevel: params.vipLevel }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Fee Data: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Fee Data: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query fee data: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query fee data: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginMyTrades.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginMyTrades.ts index 36e82fbc..479af567 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginMyTrades.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginMyTrades.ts @@ -1,47 +1,54 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginMyTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginMyTrades(server: McpServer) { - server.tool( - "BinanceIsolatedMarginMyTrades", - "Query trade history in isolated margin account for a specific symbol.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - orderId: z.number().int().optional().describe("Filter by order ID"), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - fromId: z.number().int().optional().describe("Trade ID to start from"), - limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getMyTrades({ - symbol: params.symbol, - isIsolated: "TRUE", - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginMyTrades", + { + description: "Query trade history in isolated margin account for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + orderId: z.number().int().optional().describe("Filter by order ID"), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + fromId: z.number().int().optional().describe("Trade ID to start from"), + limit: z.number().int().optional().describe("Number of results (default 500, max 1000)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getMyTrades({ + symbol: params.symbol, + isIsolated: "TRUE", + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Trades for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query trades: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginNewOrder.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginNewOrder.ts index 10382851..42659f1c 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginNewOrder.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginNewOrder.ts @@ -1,63 +1,99 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginNewOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginNewOrder(server: McpServer) { - server.tool( - "BinanceIsolatedMarginNewOrder", + server.registerTool( + "BinanceIsolatedMarginNewOrder", + { + description: "Post a new order in isolated margin account. Supports various order types including LIMIT, MARKET, STOP_LOSS, etc.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - type: z.enum(["LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]).describe("Order type"), - quantity: z.string().optional().describe("Order quantity"), - quoteOrderQty: z.string().optional().describe("Quote order quantity for MARKET orders"), - price: z.string().optional().describe("Order price (required for LIMIT orders)"), - stopPrice: z.string().optional().describe("Stop price for STOP_LOSS and TAKE_PROFIT orders"), - newClientOrderId: z.string().optional().describe("Unique client order ID"), - icebergQty: z.string().optional().describe("Iceberg quantity"), - newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), - sideEffectType: z.enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]).optional().describe("Side effect type for margin orders"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - selfTradePreventionMode: z.enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]).optional().describe("Self-trade prevention mode"), - autoRepayAtCancel: z.boolean().optional().describe("Auto repay at cancel, only for AUTO_BORROW_REPAY"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.newOrder({ - symbol: params.symbol, - isIsolated: "TRUE", - side: params.side, - type: params.type, - ...(params.quantity && { quantity: params.quantity }), - ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.icebergQty && { icebergQty: params.icebergQty }), - ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), - ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.selfTradePreventionMode && { selfTradePreventionMode: params.selfTradePreventionMode }), - ...(params.autoRepayAtCancel !== undefined && { autoRepayAtCancel: params.autoRepayAtCancel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", + ]) + .describe("Order type"), + quantity: z.string().optional().describe("Order quantity"), + quoteOrderQty: z.string().optional().describe("Quote order quantity for MARKET orders"), + price: z.string().optional().describe("Order price (required for LIMIT orders)"), + stopPrice: z + .string() + .optional() + .describe("Stop price for STOP_LOSS and TAKE_PROFIT orders"), + newClientOrderId: z.string().optional().describe("Unique client order ID"), + icebergQty: z.string().optional().describe("Iceberg quantity"), + newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), + sideEffectType: z + .enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]) + .optional() + .describe("Side effect type for margin orders"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + selfTradePreventionMode: z + .enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]) + .optional() + .describe("Self-trade prevention mode"), + autoRepayAtCancel: z + .boolean() + .optional() + .describe("Auto repay at cancel, only for AUTO_BORROW_REPAY"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.newOrder({ + symbol: params.symbol, + isIsolated: "TRUE", + side: params.side, + type: params.type, + ...(params.quantity && { quantity: params.quantity }), + ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.icebergQty && { icebergQty: params.icebergQty }), + ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), + ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.selfTradePreventionMode && { + selfTradePreventionMode: params.selfTradePreventionMode, + }), + ...(params.autoRepayAtCancel !== undefined && { + autoRepayAtCancel: params.autoRepayAtCancel, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated margin order placed successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated margin order placed successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place isolated margin order: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to place isolated margin order: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginOpenOrders.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginOpenOrders.ts index c1909583..ade3bdd1 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginOpenOrders.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginOpenOrders.ts @@ -1,37 +1,44 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginOpenOrders(server: McpServer) { - server.tool( - "BinanceIsolatedMarginOpenOrders", - "Query all open orders in isolated margin account for a specific symbol.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getOpenOrders({ - symbol: params.symbol, - isIsolated: "TRUE", - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginOpenOrders", + { + description: "Query all open orders in isolated margin account for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getOpenOrders({ + symbol: params.symbol, + isIsolated: "TRUE", + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Open Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Open Orders for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginPair.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginPair.ts index b1c8ea9f..d0a3a66f 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginPair.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginPair.ts @@ -1,36 +1,44 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginPair.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginPair(server: McpServer) { - server.tool( - "BinanceIsolatedMarginPair", + server.registerTool( + "BinanceIsolatedMarginPair", + { + description: "Query isolated margin symbol info including margin ratio, base/quote assets, and status.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedMarginPairs({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedMarginPairs({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Pair Info for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Pair Info for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query pair info: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query pair info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginRepay.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginRepay.ts index 10f50803..2b235335 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginRepay.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginRepay.ts @@ -5,45 +5,53 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/isolatedMarginRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginRepay(server: McpServer) { - server.tool( - "BinanceIsolatedMarginRepay", - "Repay borrowed assets in isolated margin account.", - { - asset: z.string().describe("Asset to repay (e.g., BTC, USDT)"), - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - amount: z.string().describe("Amount to repay"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.marginBorrowRepay({ - asset: params.asset, - isIsolated: "TRUE", - symbol: params.symbol, - amount: params.amount, - type: "REPAY", - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginRepay", + { + description: "Repay borrowed assets in isolated margin account.", + inputSchema: { + asset: z.string().describe("Asset to repay (e.g., BTC, USDT)"), + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + amount: z.string().describe("Amount to repay"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.marginBorrowRepay({ + asset: params.asset, + isIsolated: "TRUE", + symbol: params.symbol, + amount: params.amount, + type: "REPAY", + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Repaid ${params.amount} ${params.asset} for ${params.symbol}: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Repaid ${params.amount} ${params.asset} for ${params.symbol}: ${JSON.stringify(data)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to repay: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to repay: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginSymbol.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginSymbol.ts index 2cb86403..8bea1ba8 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginSymbol.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginSymbol.ts @@ -5,39 +5,47 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/isolatedMarginSymbol.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginSymbol(server: McpServer) { - server.tool( - "BinanceIsolatedMarginSymbol", - "Query isolated margin symbol information for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.queryIsolatedMarginSymbol({ - symbol: params.symbol, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginSymbol", + { + description: "Query isolated margin symbol information for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.queryIsolatedMarginSymbol({ + symbol: params.symbol, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Symbol Info for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Isolated Margin Symbol Info for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query symbol info: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query symbol info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTierData.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTierData.ts index 02683f80..e0cc31d6 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTierData.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTierData.ts @@ -1,38 +1,46 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginTierData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginTierData(server: McpServer) { - server.tool( - "BinanceIsolatedMarginTierData", + server.registerTool( + "BinanceIsolatedMarginTierData", + { + description: "Query isolated margin tier data showing leverage tiers and maintenance margin ratios for a symbol.", - { - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - tier: z.number().int().optional().describe("Specific tier to query"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getIsolatedMarginTier({ - symbol: params.symbol, - ...(params.tier !== undefined && { tier: params.tier }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + tier: z.number().int().optional().describe("Specific tier to query"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getIsolatedMarginTier({ + symbol: params.symbol, + ...(params.tier !== undefined && { tier: params.tier }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Tier Data for ${params.symbol}: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated Margin Tier Data for ${params.symbol}: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query tier data: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query tier data: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransfer.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransfer.ts index 4c49fca1..242d488a 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransfer.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransfer.ts @@ -1,44 +1,52 @@ // src/tools/binance-margin/isolated-margin-api/isolatedMarginTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginTransfer(server: McpServer) { - server.tool( - "BinanceIsolatedMarginTransfer", + server.registerTool( + "BinanceIsolatedMarginTransfer", + { + description: "Transfer assets between spot wallet and isolated margin account for a specific symbol.", - { - asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), - symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), - amount: z.string().describe("Amount to transfer"), - transFrom: z.enum(["SPOT", "ISOLATED_MARGIN"]).describe("Transfer from account type"), - transTo: z.enum(["SPOT", "ISOLATED_MARGIN"]).describe("Transfer to account type"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.transfer({ - asset: params.asset, - symbol: params.symbol, - amount: params.amount, - transFrom: params.transFrom, - transTo: params.transTo, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), + symbol: z.string().describe("Isolated margin symbol (e.g., BTCUSDT)"), + amount: z.string().describe("Amount to transfer"), + transFrom: z.enum(["SPOT", "ISOLATED_MARGIN"]).describe("Transfer from account type"), + transTo: z.enum(["SPOT", "ISOLATED_MARGIN"]).describe("Transfer to account type"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.transfer({ + asset: params.asset, + symbol: params.symbol, + amount: params.amount, + transFrom: params.transFrom, + transTo: params.transTo, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `Isolated margin transfer successful: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Isolated margin transfer successful: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransferHistory.ts b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransferHistory.ts index 646391c0..44197130 100644 --- a/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransferHistory.ts +++ b/src/tools/binance-margin/isolated-margin-api/isolatedMarginTransferHistory.ts @@ -5,55 +5,63 @@ * @license Apache-2.0 */ // src/tools/binance-margin/isolated-margin-api/isolatedMarginTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceIsolatedMarginTransferHistory(server: McpServer) { - server.tool( - "BinanceIsolatedMarginTransferHistory", - "Query isolated margin transfer history.", - { - symbol: z.string().optional().describe("Isolated margin symbol"), - asset: z.string().optional().describe("Asset"), - transFrom: z.enum(["SPOT", "ISOLATED_MARGIN"]).optional().describe("Transfer from"), - transTo: z.enum(["SPOT", "ISOLATED_MARGIN"]).optional().describe("Transfer to"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - current: z.number().int().optional().describe("Current page, default 1"), - size: z.number().int().optional().describe("Page size, default 10, max 100"), - archived: z.boolean().optional().describe("Query archived data"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.getIsolatedMarginTransferHistory({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.asset && { asset: params.asset }), - ...(params.transFrom && { transFrom: params.transFrom }), - ...(params.transTo && { transTo: params.transTo }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.archived !== undefined && { archived: params.archived }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceIsolatedMarginTransferHistory", + { + description: "Query isolated margin transfer history.", + inputSchema: { + symbol: z.string().optional().describe("Isolated margin symbol"), + asset: z.string().optional().describe("Asset"), + transFrom: z.enum(["SPOT", "ISOLATED_MARGIN"]).optional().describe("Transfer from"), + transTo: z.enum(["SPOT", "ISOLATED_MARGIN"]).optional().describe("Transfer to"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + current: z.number().int().optional().describe("Current page, default 1"), + size: z.number().int().optional().describe("Page size, default 10, max 100"), + archived: z.boolean().optional().describe("Query archived data"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.getIsolatedMarginTransferHistory({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.asset && { asset: params.asset }), + ...(params.transFrom && { transFrom: params.transFrom }), + ...(params.transTo && { transTo: params.transTo }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.archived !== undefined && { archived: params.archived }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Isolated Margin Transfer History: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Isolated Margin Transfer History: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to query transfer history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/isolated-margin-api/toggleBnbBurn.ts b/src/tools/binance-margin/isolated-margin-api/toggleBnbBurn.ts index 8bff5210..6bd698fc 100644 --- a/src/tools/binance-margin/isolated-margin-api/toggleBnbBurn.ts +++ b/src/tools/binance-margin/isolated-margin-api/toggleBnbBurn.ts @@ -1,38 +1,52 @@ // src/tools/binance-margin/isolated-margin-api/toggleBnbBurn.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceToggleBnbBurn(server: McpServer) { - server.tool( - "BinanceToggleBnbBurn", + server.registerTool( + "BinanceToggleBnbBurn", + { + description: "Toggle BNB burn on spot trade and margin interest. When enabled, uses BNB to pay for trading fees and margin interest at a discount.", - { - spotBNBBurn: z.enum(["true", "false"]).optional().describe("Enable/disable BNB burn for spot trading fees"), - interestBNBBurn: z.enum(["true", "false"]).optional().describe("Enable/disable BNB burn for margin interest"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const data = await marginClient.getAccount({ - ...(params.spotBNBBurn && { spotBNBBurn: params.spotBNBBurn }), - ...(params.interestBNBBurn && { interestBNBBurn: params.interestBNBBurn }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + spotBNBBurn: z + .enum(["true", "false"]) + .optional() + .describe("Enable/disable BNB burn for spot trading fees"), + interestBNBBurn: z + .enum(["true", "false"]) + .optional() + .describe("Enable/disable BNB burn for margin interest"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const data = await marginClient.getAccount({ + ...(params.spotBNBBurn && { spotBNBBurn: params.spotBNBBurn }), + ...(params.interestBNBBurn && { interestBNBBurn: params.interestBNBBurn }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + return { + content: [ + { + type: "text", + text: `BNB Burn settings updated: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `BNB Burn settings updated: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to toggle BNB burn: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to toggle BNB burn: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/margin-order-api/index.ts b/src/tools/binance-margin/margin-order-api/index.ts index c2a603e9..037e2be1 100644 --- a/src/tools/binance-margin/margin-order-api/index.ts +++ b/src/tools/binance-margin/margin-order-api/index.ts @@ -5,18 +5,19 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceMarginNewOco } from "./marginNewOco.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceMarginCancelOco } from "./marginCancelOco.js"; -import { registerBinanceMarginGetOco } from "./marginGetOco.js"; import { registerBinanceMarginGetAllOco } from "./marginGetAllOco.js"; +import { registerBinanceMarginGetOco } from "./marginGetOco.js"; import { registerBinanceMarginGetOpenOco } from "./marginGetOpenOco.js"; +import { registerBinanceMarginNewOco } from "./marginNewOco.js"; export function registerBinanceMarginOrderTools(server: McpServer) { - // OCO Orders - registerBinanceMarginNewOco(server); - registerBinanceMarginCancelOco(server); - registerBinanceMarginGetOco(server); - registerBinanceMarginGetAllOco(server); - registerBinanceMarginGetOpenOco(server); + // OCO Orders + registerBinanceMarginNewOco(server); + registerBinanceMarginCancelOco(server); + registerBinanceMarginGetOco(server); + registerBinanceMarginGetAllOco(server); + registerBinanceMarginGetOpenOco(server); } diff --git a/src/tools/binance-margin/margin-order-api/marginCancelOco.ts b/src/tools/binance-margin/margin-order-api/marginCancelOco.ts index fcc5235e..6ead884a 100644 --- a/src/tools/binance-margin/margin-order-api/marginCancelOco.ts +++ b/src/tools/binance-margin/margin-order-api/marginCancelOco.ts @@ -5,55 +5,72 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/marginCancelOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceMarginCancelOco(server: McpServer) { - server.tool( - "BinanceMarginCancelOco", + server.registerTool( + "BinanceMarginCancelOco", + { + description: "Cancel an entire OCO (One-Cancels-the-Other) order in Margin account. Both legs will be cancelled.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderListId: z.number().int().optional().describe("Order list ID"), - listClientOrderId: z.string().optional().describe("Client order list ID"), - newClientOrderId: z.string().optional().describe("New client order ID for this cancel request"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin, default FALSE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - // Either orderListId or listClientOrderId must be provided - if (params.orderListId === undefined && !params.listClientOrderId) { - return { - content: [{ type: "text", text: "Either orderListId or listClientOrderId must be provided" }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderListId: z.number().int().optional().describe("Order list ID"), + listClientOrderId: z.string().optional().describe("Client order list ID"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for this cancel request"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin, default FALSE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + // Either orderListId or listClientOrderId must be provided + if (params.orderListId === undefined && !params.listClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderListId or listClientOrderId must be provided" }, + ], + isError: true, + }; + } - const response = await marginClient.restAPI.marginAccountCancelOco({ - symbol: params.symbol, - ...(params.orderListId !== undefined && { orderListId: params.orderListId }), - ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + const response = await (marginClient as any).restAPI.marginAccountCancelOco({ + symbol: params.symbol, + ...(params.orderListId !== undefined && { orderListId: params.orderListId }), + ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Margin OCO order cancelled successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel margin OCO order: ${errorMessage}` }], - isError: true - }; - } - } - ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Margin OCO order cancelled successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel margin OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/margin-order-api/marginGetAllOco.ts b/src/tools/binance-margin/margin-order-api/marginGetAllOco.ts index 45da02ac..19735ce7 100644 --- a/src/tools/binance-margin/margin-order-api/marginGetAllOco.ts +++ b/src/tools/binance-margin/margin-order-api/marginGetAllOco.ts @@ -5,49 +5,66 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/marginGetAllOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceMarginGetAllOco(server: McpServer) { - server.tool( - "BinanceMarginGetAllOco", + server.registerTool( + "BinanceMarginGetAllOco", + { + description: "Query all OCO (One-Cancels-the-Other) orders in Margin account, both open and closed.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (mandatory for isolated margin)"), - fromId: z.number().int().optional().describe("Order list ID to start from"), - startTime: z.number().int().optional().describe("Start timestamp in ms"), - endTime: z.number().int().optional().describe("End timestamp in ms"), - limit: z.number().int().optional().describe("Number of results, default 500, max 1000"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin, default FALSE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.queryMarginAccountsAllOco({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.fromId !== undefined && { fromId: params.fromId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z + .string() + .optional() + .describe("Symbol of the trading pair (mandatory for isolated margin)"), + fromId: z.number().int().optional().describe("Order list ID to start from"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().optional().describe("Number of results, default 500, max 1000"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin, default FALSE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.queryMarginAccountsAllOco({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.fromId !== undefined && { fromId: params.fromId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `All Margin OCO orders: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `All Margin OCO orders: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query all margin OCO orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to query all margin OCO orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/margin-order-api/marginGetOco.ts b/src/tools/binance-margin/margin-order-api/marginGetOco.ts index 9f16c005..00307a56 100644 --- a/src/tools/binance-margin/margin-order-api/marginGetOco.ts +++ b/src/tools/binance-margin/margin-order-api/marginGetOco.ts @@ -5,53 +5,70 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/marginGetOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceMarginGetOco(server: McpServer) { - server.tool( - "BinanceMarginGetOco", + server.registerTool( + "BinanceMarginGetOco", + { + description: "Query a specific OCO (One-Cancels-the-Other) order in Margin account by orderListId or listClientOrderId.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (mandatory for isolated margin)"), - orderListId: z.number().int().optional().describe("Order list ID"), - origClientOrderId: z.string().optional().describe("Original client order list ID"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin, default FALSE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - // Either orderListId or origClientOrderId must be provided - if (params.orderListId === undefined && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "Either orderListId or origClientOrderId must be provided" }], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .optional() + .describe("Symbol of the trading pair (mandatory for isolated margin)"), + orderListId: z.number().int().optional().describe("Order list ID"), + origClientOrderId: z.string().optional().describe("Original client order list ID"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin, default FALSE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + // Either orderListId or origClientOrderId must be provided + if (params.orderListId === undefined && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "Either orderListId or origClientOrderId must be provided" }, + ], + isError: true, + }; + } - const response = await marginClient.restAPI.queryMarginAccountsOco({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.orderListId !== undefined && { orderListId: params.orderListId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + const response = await (marginClient as any).restAPI.queryMarginAccountsOco({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.orderListId !== undefined && { orderListId: params.orderListId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Margin OCO order details: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query margin OCO order: ${errorMessage}` }], - isError: true - }; - } - } - ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Margin OCO order details: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to query margin OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/margin-order-api/marginGetOpenOco.ts b/src/tools/binance-margin/margin-order-api/marginGetOpenOco.ts index e72fd055..9a99f15d 100644 --- a/src/tools/binance-margin/margin-order-api/marginGetOpenOco.ts +++ b/src/tools/binance-margin/margin-order-api/marginGetOpenOco.ts @@ -5,41 +5,57 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/marginGetOpenOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceMarginGetOpenOco(server: McpServer) { - server.tool( - "BinanceMarginGetOpenOco", - "Query all open OCO (One-Cancels-the-Other) orders in Margin account.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (mandatory for isolated margin)"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin, default FALSE"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.queryMarginAccountsOpenOco({ - ...(params.symbol && { symbol: params.symbol }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceMarginGetOpenOco", + { + description: "Query all open OCO (One-Cancels-the-Other) orders in Margin account.", + inputSchema: { + symbol: z + .string() + .optional() + .describe("Symbol of the trading pair (mandatory for isolated margin)"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin, default FALSE"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.queryMarginAccountsOpenOco({ + ...(params.symbol && { symbol: params.symbol }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Open Margin OCO orders: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Open Margin OCO orders: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to query open margin OCO orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to query open margin OCO orders: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-margin/margin-order-api/marginNewOco.ts b/src/tools/binance-margin/margin-order-api/marginNewOco.ts index 16ce3bba..9e9b3666 100644 --- a/src/tools/binance-margin/margin-order-api/marginNewOco.ts +++ b/src/tools/binance-margin/margin-order-api/marginNewOco.ts @@ -5,73 +5,99 @@ * @license Apache-2.0 */ // src/tools/binance-margin/margin-order-api/marginNewOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { marginClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { marginClient } from "../../../config/binanceClient.js"; + export function registerBinanceMarginNewOco(server: McpServer) { - server.tool( - "BinanceMarginNewOco", + server.registerTool( + "BinanceMarginNewOco", + { + description: "Place a new OCO (One-Cancels-the-Other) order in Margin account. Creates both a stop-loss and take-profit order simultaneously. ⚠️ WARNING: OCO orders involve leverage and carry liquidation risk.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side"), - quantity: z.number().describe("Order quantity"), - price: z.number().describe("Limit order price"), - stopPrice: z.number().describe("Stop loss trigger price"), - stopLimitPrice: z.number().optional().describe("Stop limit order price (if stop limit order)"), - stopLimitTimeInForce: z.enum(["GTC", "FOK", "IOC"]).optional().describe("Time in force for stop limit leg"), - listClientOrderId: z.string().optional().describe("Unique ID for the order list"), - limitClientOrderId: z.string().optional().describe("Unique ID for the limit order"), - stopClientOrderId: z.string().optional().describe("Unique ID for the stop order"), - limitIcebergQty: z.number().optional().describe("Iceberg quantity for limit leg"), - stopIcebergQty: z.number().optional().describe("Iceberg quantity for stop leg"), - newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), - sideEffectType: z.enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]).optional() - .describe("Side effect type for margin orders"), - isIsolated: z.enum(["TRUE", "FALSE"]).optional().describe("For isolated margin, default FALSE"), - selfTradePreventionMode: z.enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]).optional() - .describe("Self-trade prevention mode"), - autoRepayAtCancel: z.boolean().optional().describe("Auto repay when order is canceled"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await marginClient.restAPI.marginAccountNewOco({ - symbol: params.symbol, - side: params.side, - quantity: params.quantity, - price: params.price, - stopPrice: params.stopPrice, - ...(params.stopLimitPrice !== undefined && { stopLimitPrice: params.stopLimitPrice }), - ...(params.stopLimitTimeInForce && { stopLimitTimeInForce: params.stopLimitTimeInForce }), - ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), - ...(params.limitClientOrderId && { limitClientOrderId: params.limitClientOrderId }), - ...(params.stopClientOrderId && { stopClientOrderId: params.stopClientOrderId }), - ...(params.limitIcebergQty !== undefined && { limitIcebergQty: params.limitIcebergQty }), - ...(params.stopIcebergQty !== undefined && { stopIcebergQty: params.stopIcebergQty }), - ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), - ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), - ...(params.isIsolated && { isIsolated: params.isIsolated }), - ...(params.selfTradePreventionMode && { selfTradePreventionMode: params.selfTradePreventionMode }), - ...(params.autoRepayAtCancel !== undefined && { autoRepayAtCancel: params.autoRepayAtCancel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side"), + quantity: z.number().describe("Order quantity"), + price: z.number().describe("Limit order price"), + stopPrice: z.number().describe("Stop loss trigger price"), + stopLimitPrice: z + .number() + .optional() + .describe("Stop limit order price (if stop limit order)"), + stopLimitTimeInForce: z + .enum(["GTC", "FOK", "IOC"]) + .optional() + .describe("Time in force for stop limit leg"), + listClientOrderId: z.string().optional().describe("Unique ID for the order list"), + limitClientOrderId: z.string().optional().describe("Unique ID for the limit order"), + stopClientOrderId: z.string().optional().describe("Unique ID for the stop order"), + limitIcebergQty: z.number().optional().describe("Iceberg quantity for limit leg"), + stopIcebergQty: z.number().optional().describe("Iceberg quantity for stop leg"), + newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), + sideEffectType: z + .enum(["NO_SIDE_EFFECT", "MARGIN_BUY", "AUTO_REPAY", "AUTO_BORROW_REPAY"]) + .optional() + .describe("Side effect type for margin orders"), + isIsolated: z + .enum(["TRUE", "FALSE"]) + .optional() + .describe("For isolated margin, default FALSE"), + selfTradePreventionMode: z + .enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_BOTH", "NONE"]) + .optional() + .describe("Self-trade prevention mode"), + autoRepayAtCancel: z.boolean().optional().describe("Auto repay when order is canceled"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (marginClient as any).restAPI.marginAccountNewOco({ + symbol: params.symbol, + side: params.side, + quantity: params.quantity, + price: params.price, + stopPrice: params.stopPrice, + ...(params.stopLimitPrice !== undefined && { stopLimitPrice: params.stopLimitPrice }), + ...(params.stopLimitTimeInForce && { stopLimitTimeInForce: params.stopLimitTimeInForce }), + ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), + ...(params.limitClientOrderId && { limitClientOrderId: params.limitClientOrderId }), + ...(params.stopClientOrderId && { stopClientOrderId: params.stopClientOrderId }), + ...(params.limitIcebergQty !== undefined && { limitIcebergQty: params.limitIcebergQty }), + ...(params.stopIcebergQty !== undefined && { stopIcebergQty: params.stopIcebergQty }), + ...(params.newOrderRespType && { newOrderRespType: params.newOrderRespType }), + ...(params.sideEffectType && { sideEffectType: params.sideEffectType }), + ...(params.isIsolated && { isIsolated: params.isIsolated }), + ...(params.selfTradePreventionMode && { + selfTradePreventionMode: params.selfTradePreventionMode, + }), + ...(params.autoRepayAtCancel !== undefined && { + autoRepayAtCancel: params.autoRepayAtCancel, + }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Margin OCO order placed successfully: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - const data = await response.data(); - return { - content: [{ - type: "text", - text: `Margin OCO order placed successfully: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place margin OCO order: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to place margin OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/index.ts b/src/tools/binance-mining/index.ts index 114d9107..987b48ee 100644 --- a/src/tools/binance-mining/index.ts +++ b/src/tools/binance-mining/index.ts @@ -1,31 +1,32 @@ // src/tools/binance-mining/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountList } from "./mining-api/accountList.js"; import { registerBinanceAcquiringAlgorithm } from "./mining-api/acquiringAlgorithm.js"; import { registerBinanceAcquiringCoinName } from "./mining-api/acquiringCoinname.js"; -import { registerBinanceHashRateResaleList } from "./mining-api/hashrateResaleList.js"; -import { registerBinanceRequestForMinerList } from "./mining-api/requestForMinerList.js"; -import { registerBinanceRequestForDetailMinerList } from "./mining-api/requestForDetailMinerList.js"; -import { registerBinanceExtraBonusList } from "./mining-api/extraBonusList.js"; -import { registerBinanceEarningsList } from "./mining-api/earningsList.js"; import { registerBinanceCancelHashRateResaleConfiguration } from "./mining-api/cancelHashrateResaleConfiguration.js"; +import { registerBinanceEarningsList } from "./mining-api/earningsList.js"; +import { registerBinanceExtraBonusList } from "./mining-api/extraBonusList.js"; import { registerBinanceHashRateResaleDetail } from "./mining-api/hashrateResaleDetail.js"; +import { registerBinanceHashRateResaleList } from "./mining-api/hashrateResaleList.js"; +import { registerBinanceHashRateResaleRequest } from "./mining-api/hashrateResaleRequest.js"; import { registerBinanceMiningAccountEarning } from "./mining-api/miningAccountEarning.js"; +import { registerBinanceRequestForDetailMinerList } from "./mining-api/requestForDetailMinerList.js"; +import { registerBinanceRequestForMinerList } from "./mining-api/requestForMinerList.js"; import { registerBinanceStatisticList } from "./mining-api/statisticList.js"; -import { registerBinanceHashRateResaleRequest } from "./mining-api/hashrateResaleRequest.js"; -import { registerBinanceAccountList } from "./mining-api/accountList.js"; export function registerBinanceMiningTools(server: McpServer) { - registerBinanceAcquiringAlgorithm(server); - registerBinanceAcquiringCoinName(server); - registerBinanceHashRateResaleList(server); - registerBinanceRequestForMinerList(server); - registerBinanceRequestForDetailMinerList(server); - registerBinanceExtraBonusList(server); - registerBinanceEarningsList(server); - registerBinanceCancelHashRateResaleConfiguration(server); - registerBinanceHashRateResaleDetail(server); - registerBinanceMiningAccountEarning(server); - registerBinanceStatisticList(server); - registerBinanceHashRateResaleRequest(server); - registerBinanceAccountList(server); + registerBinanceAcquiringAlgorithm(server); + registerBinanceAcquiringCoinName(server); + registerBinanceHashRateResaleList(server); + registerBinanceRequestForMinerList(server); + registerBinanceRequestForDetailMinerList(server); + registerBinanceExtraBonusList(server); + registerBinanceEarningsList(server); + registerBinanceCancelHashRateResaleConfiguration(server); + registerBinanceHashRateResaleDetail(server); + registerBinanceMiningAccountEarning(server); + registerBinanceStatisticList(server); + registerBinanceHashRateResaleRequest(server); + registerBinanceAccountList(server); } diff --git a/src/tools/binance-mining/mining-api/accountList.ts b/src/tools/binance-mining/mining-api/accountList.ts index 068013a9..cff3381d 100644 --- a/src/tools/binance-mining/mining-api/accountList.ts +++ b/src/tools/binance-mining/mining-api/accountList.ts @@ -1,49 +1,59 @@ // src/tools/binance-mining/mining-api/accountList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceAccountList(server: McpServer) { - server.tool( - "BinanceAccountList", + server.registerTool( + "BinanceAccountList", + { + description: "Retrieve hashrate statistics for a mining account. It returns both hourly (H_hashrate) and daily (D_hashrate) data, including timestamps, hashrate values, and rejection rates.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.accountList({ - algo: params.algo, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.accountList({ + algo: params.algo, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved hashrate statistics for a mining account.. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved hashrate statistics for a mining account.. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve hashrate statistics for a mining account.. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve hashrate statistics for a mining account.. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/acquiringAlgorithm.ts b/src/tools/binance-mining/mining-api/acquiringAlgorithm.ts index 0aef5307..df7ed419 100644 --- a/src/tools/binance-mining/mining-api/acquiringAlgorithm.ts +++ b/src/tools/binance-mining/mining-api/acquiringAlgorithm.ts @@ -1,40 +1,44 @@ // src/tools/binance-mining/mining-api/acquiringAlgorithm.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { miningClient } from "../../../config/binanceClient.js"; export function registerBinanceAcquiringAlgorithm(server: McpServer) { - server.tool( - "BinanceAcquiringAlgorithm", + server.registerTool( + "BinanceAcquiringAlgorithm", + { + description: "Retrieve a list of available mining algorithms, including their name, ID, sequence, and unit.", - {}, - async () => { - try { - const response = await miningClient.restAPI.acquiringAlgorithm(); + }, + async () => { + try { + const response = await miningClient.restAPI.acquiringAlgorithm(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve a list of available mining algorithms. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve a list of available mining algorithms. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of available mining algorithms: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of available mining algorithms: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/acquiringCoinname.ts b/src/tools/binance-mining/mining-api/acquiringCoinname.ts index ef422b24..852f5276 100644 --- a/src/tools/binance-mining/mining-api/acquiringCoinname.ts +++ b/src/tools/binance-mining/mining-api/acquiringCoinname.ts @@ -1,38 +1,42 @@ // src/tools/binance-mining/mining-api/acquiringCoinname.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { miningClient } from "../../../config/binanceClient.js"; export function registerBinanceAcquiringCoinName(server: McpServer) { - server.tool( - "BinanceAcquiringCoinName", + server.registerTool( + "BinanceAcquiringCoinName", + { + description: "Fetch supported mining coins with details like coin name, ID, algorithm name, and associated algorithm ID.", - {}, - async () => { - try { - const response = await miningClient.restAPI.acquiringCoinname(); + }, + async () => { + try { + const response = await miningClient.restAPI.acquiringCoinname(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched supported mining coins. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched supported mining coins. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetched supported mining coins: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetched supported mining coins: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts b/src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts index 1caed1c1..0db4a335 100644 --- a/src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts +++ b/src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts @@ -1,49 +1,55 @@ // src/tools/binance-mining/mining-api/cancelHashrateResaleConfiguration.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceCancelHashRateResaleConfiguration(server: McpServer) { - server.tool( - "BinanceCancelHashRateResaleConfiguration", + server.registerTool( + "BinanceCancelHashRateResaleConfiguration", + { + description: "Cancel an existing hashrate resale configuration using the mining ID and account details.", - { - configId: z.number().int().describe("Mining ID").min(1), - userName: z.string().min(1).describe("Mining Account"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.cancelHashrateResaleConfiguration({ - configId: params.configId, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + configId: z.number().int().describe("Mining ID").min(1), + userName: z.string().min(1).describe("Mining Account"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.cancelHashrateResaleConfiguration({ + configId: params.configId, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully canceled an existing hashrate resale configuration. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully canceled an existing hashrate resale configuration. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to canceled an existing hashrate resale configuration. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to canceled an existing hashrate resale configuration. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/earningsList.ts b/src/tools/binance-mining/mining-api/earningsList.ts index 06a4740b..5067ff6c 100644 --- a/src/tools/binance-mining/mining-api/earningsList.ts +++ b/src/tools/binance-mining/mining-api/earningsList.ts @@ -1,64 +1,82 @@ // src/tools/binance-mining/mining-api/earningsList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceEarningsList(server: McpServer) { - server.tool( - "BinanceEarningsList", + server.registerTool( + "BinanceEarningsList", + { + description: "Retrieves list of earnings related to mining activities, including transferred hashrate, daily hashrate, profit amount, and the status of the payment (unpaid, paying, or paid).", - { - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - coin: z.string().optional().describe("Coin name (optional)"), - startDate: z.number().optional().describe("Search start date (milliseconds timestamp, optional)"), - endDate: z.number().optional().describe("Search end date (milliseconds timestamp, optional)"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.earningsList({ - algo: params.algo, - userName: params.userName, - ...(params.coin && { coin: params.coin }), - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + coin: z.string().optional().describe("Coin name (optional)"), + startDate: z + .number() + .optional() + .describe("Search start date (milliseconds timestamp, optional)"), + endDate: z + .number() + .optional() + .describe("Search end date (milliseconds timestamp, optional)"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.earningsList({ + algo: params.algo, + userName: params.userName, + ...(params.coin && { coin: params.coin }), + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved list of earnings related to mining activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved list of earnings related to mining activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve list of earnings related to mining activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve list of earnings related to mining activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/extraBonusList.ts b/src/tools/binance-mining/mining-api/extraBonusList.ts index 0a46c53b..fa6c330d 100644 --- a/src/tools/binance-mining/mining-api/extraBonusList.ts +++ b/src/tools/binance-mining/mining-api/extraBonusList.ts @@ -1,58 +1,76 @@ // src/tools/binance-mining/mining-api/extraBonusList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceExtraBonusList(server: McpServer) { - server.tool( - "BinanceExtraBonusList", + server.registerTool( + "BinanceExtraBonusList", + { + description: "Retrieves extra bonuses related to mining activities, including merged mining, activity bonuses, rebates, smart pool bonuses, income transfers, and pool savings.", - { - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - coin: z.string().optional().describe("Coin name (optional)"), - startDate: z.number().optional().describe("Search start date (milliseconds timestamp, optional)"), - endDate: z.number().optional().describe("Search end date (milliseconds timestamp, optional)"), - pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.extraBonusList({ - algo: params.algo, - userName: params.userName, - ...(params.coin && { coin: params.coin }), - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + coin: z.string().optional().describe("Coin name (optional)"), + startDate: z + .number() + .optional() + .describe("Search start date (milliseconds timestamp, optional)"), + endDate: z + .number() + .optional() + .describe("Search end date (milliseconds timestamp, optional)"), + pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.extraBonusList({ + algo: params.algo, + userName: params.userName, + ...(params.coin && { coin: params.coin }), + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved extra bonuses related to mining activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved extra bonuses related to mining activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve extra bonuses related to mining activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve extra bonuses related to mining activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/hashrateResaleDetail.ts b/src/tools/binance-mining/mining-api/hashrateResaleDetail.ts index fb286b2e..5af29edc 100644 --- a/src/tools/binance-mining/mining-api/hashrateResaleDetail.ts +++ b/src/tools/binance-mining/mining-api/hashrateResaleDetail.ts @@ -1,58 +1,70 @@ // src/tools/binance-mining/mining-api/hashrateResaleDetail.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleDetail(server: McpServer) { - server.tool( - "BinanceHashRateResaleDetail", + server.registerTool( + "BinanceHashRateResaleDetail", + { + description: "Retrieves details of hashrate resale transactions, including the transferring and receiving subaccounts, algorithm, hash rate, transfer date, and associated income.", - { - configId: z.number().int().min(1).describe("Mining ID"), - userName: z.string().min(1).describe("Mining Account"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z.number().int().min(10).max(200).optional().describe("Number of pages, minimum 10, maximum 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleDetail({ - configId: params.configId, - userName: params.userName, - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + configId: z.number().int().min(1).describe("Mining ID"), + userName: z.string().min(1).describe("Mining Account"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of pages, minimum 10, maximum 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await (miningClient as any).restAPI.hashrateResaleDetail({ + configId: params.configId, + userName: params.userName, + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + } as any); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved details of hashrate resale transactions. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved details of hashrate resale transactions. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve details of hashrate resale transactions. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve details of hashrate resale transactions. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/hashrateResaleList.ts b/src/tools/binance-mining/mining-api/hashrateResaleList.ts index 83ee293f..328fd0de 100644 --- a/src/tools/binance-mining/mining-api/hashrateResaleList.ts +++ b/src/tools/binance-mining/mining-api/hashrateResaleList.ts @@ -1,60 +1,70 @@ // src/tools/binance-mining/mining-api/hashrateResaleList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleList(server: McpServer) { - server.tool( - "BinanceHashRateResaleList", + server.registerTool( + "BinanceHashRateResaleList", + { + description: "Returns the list of hashRate resale configurations including transfer details such as algorithm, hashrate amount, sender and receiver pool usernames, start and end dates, and status of the transfer.", - { - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is the first page starting from 1"), - pageSize: z - .number() - .int() - .min(10) - .max(200) - .optional() - .describe("Number of records per page, min 10, max 200"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleList({ - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is the first page starting from 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of records per page, min 10, max 200"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.hashrateResaleList({ + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully return the list of hashRate resale configurations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully return the list of hashRate resale configurations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to return the list of hashRate resale configurations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to return the list of hashRate resale configurations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/hashrateResaleRequest.ts b/src/tools/binance-mining/mining-api/hashrateResaleRequest.ts index 408caca8..6f81a5b4 100644 --- a/src/tools/binance-mining/mining-api/hashrateResaleRequest.ts +++ b/src/tools/binance-mining/mining-api/hashrateResaleRequest.ts @@ -1,60 +1,70 @@ // src/tools/binance-mining/mining-api/hashrateResaleRequest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceHashRateResaleRequest(server: McpServer) { - server.tool( - "BinanceHashRateResaleRequest", + server.registerTool( + "BinanceHashRateResaleRequest", + { + description: "Retrieve a request for setting up a hashrate resale, specifying the mining account, algorithm, start and end times, target mining account for resale, and the amount of hashrate to transfer", - { - userName: z.string().min(1).describe("Mining Account"), - algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), - endDate: z.number().int().describe("Resale End Time (Millisecond timestamp)"), - startDate: z.number().int().describe("Resale Start Time (Millisecond timestamp)"), - toPoolUser: z.string().min(1).describe("Mining Account of the recipient pool user"), - hashRate: z - .number() - .int() - .describe("Resale hashrate h/s must be transferred (BTC > 500000000000, ETH > 500000)"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.hashrateResaleRequest({ - userName: params.userName, - algo: params.algo, - endDate: params.endDate, - startDate: params.startDate, - toPoolUser: params.toPoolUser, - hashRate: params.hashRate, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + userName: z.string().min(1).describe("Mining Account"), + algo: z.string().min(1).describe("Transfer algorithm (e.g., sha256)"), + endDate: z.number().int().describe("Resale End Time (Millisecond timestamp)"), + startDate: z.number().int().describe("Resale Start Time (Millisecond timestamp)"), + toPoolUser: z.string().min(1).describe("Mining Account of the recipient pool user"), + hashRate: z + .number() + .int() + .describe("Resale hashrate h/s must be transferred (BTC > 500000000000, ETH > 500000)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.hashrateResaleRequest({ + userName: params.userName, + algo: params.algo, + endDate: params.endDate, + startDate: params.startDate, + toPoolUser: params.toPoolUser, + hashRate: params.hashRate, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved request for setting up a hashrate resale. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved request for setting up a hashrate resale. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve request for setting up a hashrate resale. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve request for setting up a hashrate resale. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/miningAccountEarning.ts b/src/tools/binance-mining/mining-api/miningAccountEarning.ts index 09399b8b..0bd262c0 100644 --- a/src/tools/binance-mining/mining-api/miningAccountEarning.ts +++ b/src/tools/binance-mining/mining-api/miningAccountEarning.ts @@ -1,61 +1,67 @@ // src/tools/binance-mining/mining-api/miningAccountEarning.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceMiningAccountEarning(server: McpServer) { - server.tool( - "BinanceMiningAccountEarning", + server.registerTool( + "BinanceMiningAccountEarning", + { + description: "Retrieves the earnings associated with a mining account, including the type of earnings (e.g., rebate, referral, refund), sub-account ID, the mining account name, and the amount earned. It also supports pagination for large data sets.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - startDate: z.number().int().optional().describe("Millisecond timestamp for the start date"), - endDate: z.number().int().optional().describe("Millisecond timestamp for the end date"), - pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), - pageSize: z - .number() - .int() - .min(10) - .max(200) - .optional() - .describe("Number of records per page, min 10, max 200"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.miningAccountEarning({ - algo: params.algo, - ...(params.startDate && { startDate: params.startDate }), - ...(params.endDate && { endDate: params.endDate }), - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.pageSize && { pageSize: params.pageSize }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + startDate: z.number().int().optional().describe("Millisecond timestamp for the start date"), + endDate: z.number().int().optional().describe("Millisecond timestamp for the end date"), + pageIndex: z.number().int().min(1).optional().describe("Page number, default is 1"), + pageSize: z + .number() + .int() + .min(10) + .max(200) + .optional() + .describe("Number of records per page, min 10, max 200"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.miningAccountEarning({ + algo: params.algo, + ...(params.startDate && { startDate: params.startDate }), + ...(params.endDate && { endDate: params.endDate }), + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.pageSize && { pageSize: params.pageSize }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the earnings associated with a mining account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the earnings associated with a mining account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the earnings associated with a mining account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the earnings associated with a mining account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/requestForDetailMinerList.ts b/src/tools/binance-mining/mining-api/requestForDetailMinerList.ts index df5fb763..3e2fde8b 100644 --- a/src/tools/binance-mining/mining-api/requestForDetailMinerList.ts +++ b/src/tools/binance-mining/mining-api/requestForDetailMinerList.ts @@ -1,51 +1,57 @@ // src/tools/binance-mining/mining-api/requestForDetailMinerList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceRequestForDetailMinerList(server: McpServer) { - server.tool( - "BinanceRequestForDetailMinerList", + server.registerTool( + "BinanceRequestForDetailMinerList", + { + description: "Retrieves detailed hashrate data for a specific miner, including both hourly (H_hashrate) and daily (D_hashrate) metrics such as time, hashrate, and rejection rate.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - workerName: z.string().min(1).describe("Miner’s name (required), e.g., bhdc1.16A10404B"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.requestForDetailMinerList({ - algo: params.algo, - userName: params.userName, - workerName: params.workerName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + workerName: z.string().min(1).describe("Miner’s name (required), e.g., bhdc1.16A10404B"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.requestForDetailMinerList({ + algo: params.algo, + userName: params.userName, + workerName: params.workerName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved detailed hashrate data for a specific miner. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved detailed hashrate data for a specific miner. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve detailed hashrate data for a specific miner. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve detailed hashrate data for a specific miner. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/requestForMinerList.ts b/src/tools/binance-mining/mining-api/requestForMinerList.ts index 009f3811..8385bacb 100644 --- a/src/tools/binance-mining/mining-api/requestForMinerList.ts +++ b/src/tools/binance-mining/mining-api/requestForMinerList.ts @@ -1,82 +1,88 @@ // src/tools/binance-mining/mining-api/requestForMinerList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceRequestForMinerList(server: McpServer) { - server.tool( - "BinanceRequestForMinerList", + server.registerTool( + "BinanceRequestForMinerList", + { + description: "Retrieves a list of miners (workers) associated with a mining account, including details such as miner name, status, real-time hashrate, 24H hashrate, rejection rate, and last submission time.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - pageIndex: z - .number() - .int() - .min(1) - .optional() - .describe("Page number, default is first page, starting from 1"), - sort: z - .number() - .int() - .min(0) - .max(1) - .optional() - .describe("Sort sequence: 0 = ascending (default), 1 = descending"), - sortColumn: z - .number() - .int() - .min(1) - .max(5) - .optional() - .describe( - `Sort by (default = 1): 1: miner name, 2: real-time computing power, 3: daily average computing power, 4: real-time rejection rate, 5: last submission time` - ), - workerStatus: z - .number() - .int() - .min(0) - .max(3) - .optional() - .describe("Miner status (default = 0): 0 = all, 1 = valid, 2 = invalid, 3 = failure"), - recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000") - }, - async (params) => { - try { - const response = await miningClient.restAPI.requestForMinerList({ - algo: params.algo, - userName: params.userName, - ...(params.pageIndex && { pageIndex: params.pageIndex }), - ...(params.sort && { sort: params.sort }), - ...(params.sortColumn && { sortColumn: params.sortColumn }), - ...(params.workerStatus && { workerStatus: params.workerStatus }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + pageIndex: z + .number() + .int() + .min(1) + .optional() + .describe("Page number, default is first page, starting from 1"), + sort: z + .number() + .int() + .min(0) + .max(1) + .optional() + .describe("Sort sequence: 0 = ascending (default), 1 = descending"), + sortColumn: z + .number() + .int() + .min(1) + .max(5) + .optional() + .describe( + `Sort by (default = 1): 1: miner name, 2: real-time computing power, 3: daily average computing power, 4: real-time rejection rate, 5: last submission time`, + ), + workerStatus: z + .number() + .int() + .min(0) + .max(3) + .optional() + .describe("Miner status (default = 0): 0 = all, 1 = valid, 2 = invalid, 3 = failure"), + recvWindow: z.number().int().optional().describe("Optional: cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.requestForMinerList({ + algo: params.algo, + userName: params.userName, + ...(params.pageIndex && { pageIndex: params.pageIndex }), + ...(params.sort && { sort: params.sort }), + ...(params.sortColumn && { sortColumn: params.sortColumn }), + ...(params.workerStatus && { workerStatus: params.workerStatus }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved a list of miners (workers) associated with a mining account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved a list of miners (workers) associated with a mining account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of miners (workers) associated with a mining account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of miners (workers) associated with a mining account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-mining/mining-api/statisticList.ts b/src/tools/binance-mining/mining-api/statisticList.ts index 3be2a279..187bbde7 100644 --- a/src/tools/binance-mining/mining-api/statisticList.ts +++ b/src/tools/binance-mining/mining-api/statisticList.ts @@ -1,48 +1,58 @@ // src/tools/binance-mining/mining-api/statisticList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { miningClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { miningClient } from "../../../config/binanceClient.js"; + export function registerBinanceStatisticList(server: McpServer) { - server.tool( - "BinanceStatisticList", + server.registerTool( + "BinanceStatisticList", + { + description: "Retrieve mining statistics for a specific account, including hash rates for the past 15 minutes and 24 hours, the number of valid and invalid mining units, and the estimated profit for today and yesterday in various cryptocurrencies.", - { - algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), - userName: z.string().min(1).describe("Mining account username"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await miningClient.restAPI.statisticList({ - algo: params.algo, - userName: params.userName, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + algo: z.string().min(1).describe("Algorithm (e.g., sha256)"), + userName: z.string().min(1).describe("Mining account username"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await miningClient.restAPI.statisticList({ + algo: params.algo, + userName: params.userName, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved mining statistics for a specific account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved mining statistics for a specific account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve mining statistics for a specific account. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve mining statistics for a specific account. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-nft/index.ts b/src/tools/binance-nft/index.ts index 36234150..da5e5703 100644 --- a/src/tools/binance-nft/index.ts +++ b/src/tools/binance-nft/index.ts @@ -1,13 +1,14 @@ // src/tools/binance-fiat/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceGetNFTAsset } from "./nft-api/getNFTAsset.js"; import { registerBinanceGetNFTDepositHistory } from "./nft-api/getNFTDepositHistory.js"; -import { registerBinanceGetNFTWithdrawHistory } from "./nft-api/getNFTWithdrawHistory.js"; import { registerBinanceGetNFTTransactionHistory } from "./nft-api/getNFTTransactionHistory.js"; -import { registerBinanceGetNFTAsset } from "./nft-api/getNFTAsset.js"; +import { registerBinanceGetNFTWithdrawHistory } from "./nft-api/getNFTWithdrawHistory.js"; export function registerBinanceNFTTools(server: McpServer) { - registerBinanceGetNFTDepositHistory(server); - registerBinanceGetNFTWithdrawHistory(server); - registerBinanceGetNFTTransactionHistory(server); - registerBinanceGetNFTAsset(server); + registerBinanceGetNFTDepositHistory(server); + registerBinanceGetNFTWithdrawHistory(server); + registerBinanceGetNFTTransactionHistory(server); + registerBinanceGetNFTAsset(server); } diff --git a/src/tools/binance-nft/nft-api/getNFTAsset.ts b/src/tools/binance-nft/nft-api/getNFTAsset.ts index e5d658b0..028b6474 100644 --- a/src/tools/binance-nft/nft-api/getNFTAsset.ts +++ b/src/tools/binance-nft/nft-api/getNFTAsset.ts @@ -1,54 +1,64 @@ // src/tools/binance-nft/nft-api/getNFTAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTAsset(server: McpServer) { - server.tool( - "BinanceGetNFTAsset", + server.registerTool( + "BinanceGetNFTAsset", + { + description: "Retrieve NFT assets associated with a user's account. It returns details about the network, contract address, and token IDs for each NFT asset.", - { - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTAsset({ - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTAsset({ + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT assets associated with a user's account. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT assets associated with a user's account. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT assets : ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT assets : ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-nft/nft-api/getNFTDepositHistory.ts b/src/tools/binance-nft/nft-api/getNFTDepositHistory.ts index 631e647c..41a7ab5a 100644 --- a/src/tools/binance-nft/nft-api/getNFTDepositHistory.ts +++ b/src/tools/binance-nft/nft-api/getNFTDepositHistory.ts @@ -1,58 +1,68 @@ // src/tools/binance-nft/nft-api/getNFTDepositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTDepositHistory(server: McpServer) { - server.tool( - "BinanceGetNFTDepositHistory", + server.registerTool( + "BinanceGetNFTDepositHistory", + { + description: "Retrieves NFT deposit history, including network, contract address, token ID, transaction ID (if available), and timestamps.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .optional() - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().optional().describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTDepositHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .optional() + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().optional().describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTDepositHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT deposit history, including network, contract address, token ID. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT deposit history, including network, contract address, token ID. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieves NFT deposit history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieves NFT deposit history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts b/src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts index 86b27c9f..ecbbc676 100644 --- a/src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts +++ b/src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts @@ -1,62 +1,72 @@ // src/tools/binance-nft/nft-api/getNFTTransactionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTTransactionHistory(server: McpServer) { - server.tool( - "BinanceGetNFTTransactionHistory", + server.registerTool( + "BinanceGetNFTTransactionHistory", + { + description: "Retrieves NFT transaction history, including purchase orders, sale orders, royalty income, primary market orders, and mint fees. It returns details about the NFT network, token IDs, contract addresses, transaction times, trade amounts, and the currencies used in the transactions.", - { - orderType: z - .number() - .describe( - "Order type: 0 for purchase order, 1 for sell order, 2 for royalty income, 3 for primary market order, 4 for mint fee" - ), - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTTransactionHistory({ - orderType: params.orderType, - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderType: z + .number() + .describe( + "Order type: 0 for purchase order, 1 for sell order, 2 for royalty income, 3 for primary market order, 4 for mint fee", + ), + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTTransactionHistory({ + orderType: params.orderType, + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT transaction history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT transaction history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT transaction history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT transaction history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts b/src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts index f2ab7722..924599a8 100644 --- a/src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts +++ b/src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts @@ -1,58 +1,68 @@ // src/tools/binance-nft/nft-api/getNFTWithdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { nftClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { nftClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetNFTWithdrawHistory(server: McpServer) { - server.tool( - "BinanceGetNFTWithdrawHistory", + server.registerTool( + "BinanceGetNFTWithdrawHistory", + { + description: "Retrieves NFT withdraw history, including network, transaction ID, contract address, token ID, withdrawal fee, fee asset, and timestamps.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(50, "Limit cannot be greater than 50") - .default(50) - .describe("Number of records to return, default 50, max 50"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await nftClient.restAPI.getNFTWithdrawHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(50, "Limit cannot be greater than 50") + .default(50) + .describe("Number of records to return, default 50, max 50"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await nftClient.restAPI.getNFTWithdrawHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved NFT withdraw history, including network, transaction ID, contract address. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved NFT withdraw history, including network, transaction ID, contract address. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve NFT withdraw history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve NFT withdraw history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/account.ts b/src/tools/binance-options/account.ts index a7ee5682..78297ad1 100644 --- a/src/tools/binance-options/account.ts +++ b/src/tools/binance-options/account.ts @@ -1,33 +1,32 @@ // src/tools/binance-options/account.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsAccount(server: McpServer) { - server.tool( - "BinanceOptionsAccount", - "Get current options account information.", - {}, - async () => { - try { - const data = await optionsClient.account(); - - return { - content: [ - { - type: "text", - text: `Options account information retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get account info: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsAccount", + { description: "Get current options account information." }, + async () => { + try { + const data = await optionsClient.account(); + + return { + content: [ + { + type: "text", + text: `Options account information retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get account info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/batchOrders.ts b/src/tools/binance-options/batchOrders.ts index 5de8a6f0..4455673f 100644 --- a/src/tools/binance-options/batchOrders.ts +++ b/src/tools/binance-options/batchOrders.ts @@ -1,38 +1,45 @@ // src/tools/binance-options/batchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsBatchOrders(server: McpServer) { - server.tool( - "BinanceOptionsBatchOrders", - "Place multiple options orders in batch.", - { - orders: z.string().describe("JSON array of orders, each containing symbol, side, type, quantity, and optionally price, timeInForce, reduceOnly, postOnly, clientOrderId") - }, - async ({ orders }) => { - try { - const params: any = { orders }; - - const data = await optionsClient.batchOrders(params); - - return { - content: [ - { - type: "text", - text: `Batch orders placed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to place batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsBatchOrders", + { + description: "Place multiple options orders in batch.", + inputSchema: { + orders: z + .string() + .describe( + "JSON array of orders, each containing symbol, side, type, quantity, and optionally price, timeInForce, reduceOnly, postOnly, clientOrderId", + ), + }, + }, + async ({ orders }) => { + try { + const params: any = { orders }; + + const data = await optionsClient.batchOrders(params); + + return { + content: [ + { + type: "text", + text: `Batch orders placed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to place batch orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/bill.ts b/src/tools/binance-options/bill.ts index 4c553658..2df98868 100644 --- a/src/tools/binance-options/bill.ts +++ b/src/tools/binance-options/bill.ts @@ -1,47 +1,53 @@ // src/tools/binance-options/bill.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsBill(server: McpServer) { - server.tool( - "BinanceOptionsBill", - "Get options account funding flow (bill history).", - { - currency: z.string().optional().describe("Currency (e.g., USDT)"), - recordId: z.number().optional().describe("Record ID to fetch from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of records to return. Default 100; max 1000.") - }, - async ({ currency, recordId, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (currency) params.currency = currency; - if (recordId !== undefined) params.recordId = recordId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.bill(params); - - return { - content: [ - { - type: "text", - text: `Bill history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get bill history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsBill", + { + description: "Get options account funding flow (bill history).", + inputSchema: { + currency: z.string().optional().describe("Currency (e.g., USDT)"), + recordId: z.number().optional().describe("Record ID to fetch from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z + .number() + .optional() + .describe("Number of records to return. Default 100; max 1000."), + }, + }, + async ({ currency, recordId, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (currency) params.currency = currency; + if (recordId !== undefined) params.recordId = recordId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.bill(params); + + return { + content: [ + { + type: "text", + text: `Bill history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get bill history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/cancelAllOrders.ts b/src/tools/binance-options/cancelAllOrders.ts index b4262300..2326b036 100644 --- a/src/tools/binance-options/cancelAllOrders.ts +++ b/src/tools/binance-options/cancelAllOrders.ts @@ -1,38 +1,41 @@ // src/tools/binance-options/cancelAllOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsCancelAllOrders(server: McpServer) { - server.tool( - "BinanceOptionsCancelAllOrders", - "Cancel all open options orders for a symbol.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = { symbol }; - - const data = await optionsClient.cancelAllOrders(params); - - return { - content: [ - { - type: "text", - text: `All orders cancelled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel all orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsCancelAllOrders", + { + description: "Cancel all open options orders for a symbol.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = { symbol }; + + const data = await optionsClient.cancelAllOrders(params); + + return { + content: [ + { + type: "text", + text: `All orders cancelled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/cancelBatchOrders.ts b/src/tools/binance-options/cancelBatchOrders.ts index c785affb..16a27b91 100644 --- a/src/tools/binance-options/cancelBatchOrders.ts +++ b/src/tools/binance-options/cancelBatchOrders.ts @@ -1,42 +1,48 @@ // src/tools/binance-options/cancelBatchOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsCancelBatchOrders(server: McpServer) { - server.tool( - "BinanceOptionsCancelBatchOrders", - "Cancel multiple options orders in batch.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - orderIds: z.string().optional().describe("Comma-separated list of order IDs to cancel"), - clientOrderIds: z.string().optional().describe("Comma-separated list of client order IDs to cancel") - }, - async ({ symbol, orderIds, clientOrderIds }) => { - try { - const params: any = { symbol }; - if (orderIds) params.orderIds = orderIds; - if (clientOrderIds) params.clientOrderIds = clientOrderIds; - - const data = await optionsClient.cancelBatchOrders(params); - - return { - content: [ - { - type: "text", - text: `Batch orders cancelled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel batch orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsCancelBatchOrders", + { + description: "Cancel multiple options orders in batch.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + orderIds: z.string().optional().describe("Comma-separated list of order IDs to cancel"), + clientOrderIds: z + .string() + .optional() + .describe("Comma-separated list of client order IDs to cancel"), + }, + }, + async ({ symbol, orderIds, clientOrderIds }) => { + try { + const params: any = { symbol }; + if (orderIds) params.orderIds = orderIds; + if (clientOrderIds) params.clientOrderIds = clientOrderIds; + + const data = await optionsClient.cancelBatchOrders(params); + + return { + content: [ + { + type: "text", + text: `Batch orders cancelled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel batch orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/cancelOrder.ts b/src/tools/binance-options/cancelOrder.ts index e65bb219..d80e4035 100644 --- a/src/tools/binance-options/cancelOrder.ts +++ b/src/tools/binance-options/cancelOrder.ts @@ -1,42 +1,45 @@ // src/tools/binance-options/cancelOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsCancelOrder(server: McpServer) { - server.tool( - "BinanceOptionsCancelOrder", - "Cancel an existing options order.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - orderId: z.number().optional().describe("Order ID"), - clientOrderId: z.string().optional().describe("Client order ID") - }, - async ({ symbol, orderId, clientOrderId }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const data = await optionsClient.cancelOrder(params); - - return { - content: [ - { - type: "text", - text: `Order cancelled successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsCancelOrder", + { + description: "Cancel an existing options order.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + orderId: z.number().optional().describe("Order ID"), + clientOrderId: z.string().optional().describe("Client order ID"), + }, + }, + async ({ symbol, orderId, clientOrderId }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const data = await optionsClient.cancelOrder(params); + + return { + content: [ + { + type: "text", + text: `Order cancelled successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/depth.ts b/src/tools/binance-options/depth.ts index 495d523c..9c43f888 100644 --- a/src/tools/binance-options/depth.ts +++ b/src/tools/binance-options/depth.ts @@ -1,40 +1,43 @@ // src/tools/binance-options/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsDepth(server: McpServer) { - server.tool( - "BinanceOptionsDepth", - "Get order book depth for an option symbol.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - limit: z.number().optional().describe("Depth limit. Default 100; max 1000.") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.depth(params); - - return { - content: [ - { - type: "text", - text: `Order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get order book depth: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsDepth", + { + description: "Get order book depth for an option symbol.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + limit: z.number().optional().describe("Depth limit. Default 100; max 1000."), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.depth(params); + + return { + content: [ + { + type: "text", + text: `Order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get order book depth: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/exchangeInfo.ts b/src/tools/binance-options/exchangeInfo.ts index 5960e653..179c3c20 100644 --- a/src/tools/binance-options/exchangeInfo.ts +++ b/src/tools/binance-options/exchangeInfo.ts @@ -1,39 +1,39 @@ // src/tools/binance-options/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsExchangeInfo(server: McpServer) { - server.tool( - "BinanceOptionsExchangeInfo", - "Get current exchange trading rules and symbol information for options.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const data = await optionsClient.exchangeInfo(params); - - return { - content: [ - { - type: "text", - text: `Exchange info retrieved successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get exchange info: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsExchangeInfo", + { + description: "Get current exchange trading rules and symbol information for options.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const data = await optionsClient.exchangeInfo(); + + return { + content: [ + { + type: "text", + text: `Exchange info retrieved successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get exchange info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/exerciseHistory.ts b/src/tools/binance-options/exerciseHistory.ts index 27b3a8d1..f4b40952 100644 --- a/src/tools/binance-options/exerciseHistory.ts +++ b/src/tools/binance-options/exerciseHistory.ts @@ -1,45 +1,48 @@ // src/tools/binance-options/exerciseHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsExerciseHistory(server: McpServer) { - server.tool( - "BinanceOptionsExerciseHistory", - "Get historical exercise records for options.", - { - underlying: z.string().optional().describe("Underlying asset (e.g., BTCUSDT)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of records to return. Default 100; max 100.") - }, - async ({ underlying, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (underlying) params.underlying = underlying; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.exerciseHistory(params); - - return { - content: [ - { - type: "text", - text: `Exercise history retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get exercise history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsExerciseHistory", + { + description: "Get historical exercise records for options.", + inputSchema: { + underlying: z.string().optional().describe("Underlying asset (e.g., BTCUSDT)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of records to return. Default 100; max 100."), + }, + }, + async ({ underlying, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (underlying) params.underlying = underlying; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.exerciseRecord(params); + + return { + content: [ + { + type: "text", + text: `Exercise history retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get exercise history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/exerciseRecord.ts b/src/tools/binance-options/exerciseRecord.ts index f8123cc8..31daa0e5 100644 --- a/src/tools/binance-options/exerciseRecord.ts +++ b/src/tools/binance-options/exerciseRecord.ts @@ -1,45 +1,51 @@ // src/tools/binance-options/exerciseRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsExerciseRecord(server: McpServer) { - server.tool( - "BinanceOptionsExerciseRecord", - "Get user's options exercise records.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of records to return. Default 100; max 1000.") - }, - async ({ symbol, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.exerciseRecord(params); - - return { - content: [ - { - type: "text", - text: `Exercise records retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get exercise records: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsExerciseRecord", + { + description: "Get user's options exercise records.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z + .number() + .optional() + .describe("Number of records to return. Default 100; max 1000."), + }, + }, + async ({ symbol, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.exerciseRecord(params); + + return { + content: [ + { + type: "text", + text: `Exercise records retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get exercise records: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/getOrder.ts b/src/tools/binance-options/getOrder.ts index 2cf4302d..2b187b4e 100644 --- a/src/tools/binance-options/getOrder.ts +++ b/src/tools/binance-options/getOrder.ts @@ -1,42 +1,45 @@ // src/tools/binance-options/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsGetOrder(server: McpServer) { - server.tool( - "BinanceOptionsGetOrder", - "Query an options order by order ID or client order ID.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - orderId: z.number().optional().describe("Order ID"), - clientOrderId: z.string().optional().describe("Client order ID") - }, - async ({ symbol, orderId, clientOrderId }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const data = await optionsClient.getOrder(params); - - return { - content: [ - { - type: "text", - text: `Order details retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsGetOrder", + { + description: "Query an options order by order ID or client order ID.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + orderId: z.number().optional().describe("Order ID"), + clientOrderId: z.string().optional().describe("Client order ID"), + }, + }, + async ({ symbol, orderId, clientOrderId }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const data = await optionsClient.getOrder(params); + + return { + content: [ + { + type: "text", + text: `Order details retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/historicalTrades.ts b/src/tools/binance-options/historicalTrades.ts index 0ffc5ce3..d924a543 100644 --- a/src/tools/binance-options/historicalTrades.ts +++ b/src/tools/binance-options/historicalTrades.ts @@ -1,42 +1,45 @@ // src/tools/binance-options/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsHistoricalTrades(server: McpServer) { - server.tool( - "BinanceOptionsHistoricalTrades", - "Get historical trades for an option symbol.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - fromId: z.number().optional().describe("Trade ID to fetch from"), - limit: z.number().optional().describe("Number of trades to return. Default 100; max 500.") - }, - async ({ symbol, fromId, limit }) => { - try { - const params: any = { symbol }; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.historicalTrades(params); - - return { - content: [ - { - type: "text", - text: `Historical trades for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get historical trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsHistoricalTrades", + { + description: "Get historical trades for an option symbol.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + limit: z.number().optional().describe("Number of trades to return. Default 100; max 500."), + }, + }, + async ({ symbol, fromId, limit }) => { + try { + const params: any = { symbol }; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.historicalTrades(params); + + return { + content: [ + { + type: "text", + text: `Historical trades for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get historical trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/historyOrders.ts b/src/tools/binance-options/historyOrders.ts index d4b5d2e7..1e8b5f28 100644 --- a/src/tools/binance-options/historyOrders.ts +++ b/src/tools/binance-options/historyOrders.ts @@ -1,46 +1,49 @@ // src/tools/binance-options/historyOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsHistoryOrders(server: McpServer) { - server.tool( - "BinanceOptionsHistoryOrders", - "Get historical options orders.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - orderId: z.number().optional().describe("Order ID to fetch from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of orders to return. Default 100; max 1000.") - }, - async ({ symbol, orderId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.historyOrders(params); - - return { - content: [ - { - type: "text", - text: `Historical orders retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get history orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsHistoryOrders", + { + description: "Get historical options orders.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + orderId: z.number().optional().describe("Order ID to fetch from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of orders to return. Default 100; max 1000."), + }, + }, + async ({ symbol, orderId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.historyOrders(params); + + return { + content: [ + { + type: "text", + text: `Historical orders retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get history orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/index.ts b/src/tools/binance-options/index.ts index 1b2ec9ef..f86d2d21 100644 --- a/src/tools/binance-options/index.ts +++ b/src/tools/binance-options/index.ts @@ -1,74 +1,72 @@ // src/tools/binance-options/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; - -// Market Data -import { registerBinanceOptionsPing } from "./ping.js"; -import { registerBinanceOptionsTime } from "./time.js"; -import { registerBinanceOptionsExchangeInfo } from "./exchangeInfo.js"; -import { registerBinanceOptionsDepth } from "./depth.js"; -import { registerBinanceOptionsTrades } from "./trades.js"; -import { registerBinanceOptionsHistoricalTrades } from "./historicalTrades.js"; -import { registerBinanceOptionsKlines } from "./klines.js"; -import { registerBinanceOptionsMark } from "./mark.js"; -import { registerBinanceOptionsTicker } from "./ticker.js"; -import { registerBinanceOptionsIndexPrice } from "./indexPrice.js"; -import { registerBinanceOptionsExerciseHistory } from "./exerciseHistory.js"; -import { registerBinanceOptionsOpenInterest } from "./openInterest.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; // Account & Trading import { registerBinanceOptionsAccount } from "./account.js"; -import { registerBinanceOptionsNewOrder } from "./newOrder.js"; import { registerBinanceOptionsBatchOrders } from "./batchOrders.js"; -import { registerBinanceOptionsCancelOrder } from "./cancelOrder.js"; +import { registerBinanceOptionsBill } from "./bill.js"; import { registerBinanceOptionsCancelAllOrders } from "./cancelAllOrders.js"; import { registerBinanceOptionsCancelBatchOrders } from "./cancelBatchOrders.js"; +import { registerBinanceOptionsCancelOrder } from "./cancelOrder.js"; +import { registerBinanceOptionsDepth } from "./depth.js"; +import { registerBinanceOptionsExchangeInfo } from "./exchangeInfo.js"; +import { registerBinanceOptionsExerciseHistory } from "./exerciseHistory.js"; +import { registerBinanceOptionsExerciseRecord } from "./exerciseRecord.js"; import { registerBinanceOptionsGetOrder } from "./getOrder.js"; -import { registerBinanceOptionsOpenOrders } from "./openOrders.js"; +import { registerBinanceOptionsHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceOptionsHistoryOrders } from "./historyOrders.js"; -import { registerBinanceOptionsPosition } from "./position.js"; -import { registerBinanceOptionsUserTrades } from "./userTrades.js"; -import { registerBinanceOptionsExerciseRecord } from "./exerciseRecord.js"; -import { registerBinanceOptionsBill } from "./bill.js"; - +import { registerBinanceOptionsIndexPrice } from "./indexPrice.js"; +import { registerBinanceOptionsKlines } from "./klines.js"; // User Data Stream -import { - registerBinanceOptionsCreateListenKey, - registerBinanceOptionsKeepAliveListenKey, - registerBinanceOptionsDeleteListenKey +import { + registerBinanceOptionsCreateListenKey, + registerBinanceOptionsDeleteListenKey, + registerBinanceOptionsKeepAliveListenKey, } from "./listenKey.js"; +import { registerBinanceOptionsMark } from "./mark.js"; +import { registerBinanceOptionsNewOrder } from "./newOrder.js"; +import { registerBinanceOptionsOpenInterest } from "./openInterest.js"; +import { registerBinanceOptionsOpenOrders } from "./openOrders.js"; +// Market Data +import { registerBinanceOptionsPing } from "./ping.js"; +import { registerBinanceOptionsPosition } from "./position.js"; +import { registerBinanceOptionsTicker } from "./ticker.js"; +import { registerBinanceOptionsTime } from "./time.js"; +import { registerBinanceOptionsTrades } from "./trades.js"; +import { registerBinanceOptionsUserTrades } from "./userTrades.js"; export function registerBinanceOptionsTools(server: McpServer) { - // Market Data - registerBinanceOptionsPing(server); - registerBinanceOptionsTime(server); - registerBinanceOptionsExchangeInfo(server); - registerBinanceOptionsDepth(server); - registerBinanceOptionsTrades(server); - registerBinanceOptionsHistoricalTrades(server); - registerBinanceOptionsKlines(server); - registerBinanceOptionsMark(server); - registerBinanceOptionsTicker(server); - registerBinanceOptionsIndexPrice(server); - registerBinanceOptionsExerciseHistory(server); - registerBinanceOptionsOpenInterest(server); - - // Account & Trading - registerBinanceOptionsAccount(server); - registerBinanceOptionsNewOrder(server); - registerBinanceOptionsBatchOrders(server); - registerBinanceOptionsCancelOrder(server); - registerBinanceOptionsCancelAllOrders(server); - registerBinanceOptionsCancelBatchOrders(server); - registerBinanceOptionsGetOrder(server); - registerBinanceOptionsOpenOrders(server); - registerBinanceOptionsHistoryOrders(server); - registerBinanceOptionsPosition(server); - registerBinanceOptionsUserTrades(server); - registerBinanceOptionsExerciseRecord(server); - registerBinanceOptionsBill(server); - - // User Data Stream - registerBinanceOptionsCreateListenKey(server); - registerBinanceOptionsKeepAliveListenKey(server); - registerBinanceOptionsDeleteListenKey(server); + // Market Data + registerBinanceOptionsPing(server); + registerBinanceOptionsTime(server); + registerBinanceOptionsExchangeInfo(server); + registerBinanceOptionsDepth(server); + registerBinanceOptionsTrades(server); + registerBinanceOptionsHistoricalTrades(server); + registerBinanceOptionsKlines(server); + registerBinanceOptionsMark(server); + registerBinanceOptionsTicker(server); + registerBinanceOptionsIndexPrice(server); + registerBinanceOptionsExerciseHistory(server); + registerBinanceOptionsOpenInterest(server); + + // Account & Trading + registerBinanceOptionsAccount(server); + registerBinanceOptionsNewOrder(server); + registerBinanceOptionsBatchOrders(server); + registerBinanceOptionsCancelOrder(server); + registerBinanceOptionsCancelAllOrders(server); + registerBinanceOptionsCancelBatchOrders(server); + registerBinanceOptionsGetOrder(server); + registerBinanceOptionsOpenOrders(server); + registerBinanceOptionsHistoryOrders(server); + registerBinanceOptionsPosition(server); + registerBinanceOptionsUserTrades(server); + registerBinanceOptionsExerciseRecord(server); + registerBinanceOptionsBill(server); + + // User Data Stream + registerBinanceOptionsCreateListenKey(server); + registerBinanceOptionsKeepAliveListenKey(server); + registerBinanceOptionsDeleteListenKey(server); } diff --git a/src/tools/binance-options/indexPrice.ts b/src/tools/binance-options/indexPrice.ts index c5f6e3e7..f760ec08 100644 --- a/src/tools/binance-options/indexPrice.ts +++ b/src/tools/binance-options/indexPrice.ts @@ -1,38 +1,41 @@ // src/tools/binance-options/indexPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsIndexPrice(server: McpServer) { - server.tool( - "BinanceOptionsIndexPrice", - "Get the underlying index price for options.", - { - underlying: z.string().describe("Underlying asset (e.g., BTCUSDT)") - }, - async ({ underlying }) => { - try { - const params: any = { underlying }; - - const data = await optionsClient.index(params); - - return { - content: [ - { - type: "text", - text: `Index price for ${underlying} retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get index price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsIndexPrice", + { + description: "Get the underlying index price for options.", + inputSchema: { + underlying: z.string().describe("Underlying asset (e.g., BTCUSDT)"), + }, + }, + async ({ underlying }) => { + try { + const params: any = { underlying }; + + const data = await optionsClient.index(params); + + return { + content: [ + { + type: "text", + text: `Index price for ${underlying} retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get index price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/klines.ts b/src/tools/binance-options/klines.ts index bb5066a5..d0026117 100644 --- a/src/tools/binance-options/klines.ts +++ b/src/tools/binance-options/klines.ts @@ -1,45 +1,50 @@ // src/tools/binance-options/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsKlines(server: McpServer) { - server.tool( - "BinanceOptionsKlines", - "Get kline/candlestick data for an option symbol.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - interval: z.enum(["1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d", "3d", "1w"]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of klines to return. Default 500; max 1500.") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.klines(params); - - return { - content: [ - { - type: "text", - text: `Klines for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsKlines", + { + description: "Get kline/candlestick data for an option symbol.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + interval: z + .enum(["1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d", "3d", "1w"]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of klines to return. Default 500; max 1500."), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.klines(params); + + return { + content: [ + { + type: "text", + text: `Klines for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/listenKey.ts b/src/tools/binance-options/listenKey.ts index 2fa0e73f..2153ebe2 100644 --- a/src/tools/binance-options/listenKey.ts +++ b/src/tools/binance-options/listenKey.ts @@ -1,98 +1,100 @@ // src/tools/binance-options/listenKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsCreateListenKey(server: McpServer) { - server.tool( - "BinanceOptionsCreateListenKey", - "Create a new listen key for options user data stream.", - {}, - async () => { - try { - const data = await optionsClient.createListenKey(); - - return { - content: [ - { - type: "text", - text: `Listen key created successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsCreateListenKey", + { description: "Create a new listen key for options user data stream." }, + async () => { + try { + const data = await optionsClient.createListenKey(); + + return { + content: [ + { + type: "text", + text: `Listen key created successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } export function registerBinanceOptionsKeepAliveListenKey(server: McpServer) { - server.tool( - "BinanceOptionsKeepAliveListenKey", - "Keep alive an existing listen key for options user data stream.", - { - listenKey: z.string().describe("The listen key to keep alive") - }, - async ({ listenKey }) => { - try { - const data = await optionsClient.keepAliveListenKey(); - - return { - content: [ - { - type: "text", - text: `Listen key renewed successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to renew listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsKeepAliveListenKey", + { + description: "Keep alive an existing listen key for options user data stream.", + inputSchema: { + listenKey: z.string().describe("The listen key to keep alive"), + }, + }, + async ({ listenKey: _listenKey }) => { + try { + const data = await optionsClient.keepAliveListenKey(); + + return { + content: [ + { + type: "text", + text: `Listen key renewed successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to renew listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } export function registerBinanceOptionsDeleteListenKey(server: McpServer) { - server.tool( - "BinanceOptionsDeleteListenKey", - "Delete an existing listen key for options user data stream.", - { - listenKey: z.string().describe("The listen key to delete") - }, - async ({ listenKey }) => { - try { - const data = await optionsClient.closeListenKey(); - - return { - content: [ - { - type: "text", - text: `Listen key deleted successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to delete listen key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsDeleteListenKey", + { + description: "Delete an existing listen key for options user data stream.", + inputSchema: { + listenKey: z.string().describe("The listen key to delete"), + }, + }, + async ({ listenKey: _listenKey }) => { + try { + const data = await optionsClient.closeListenKey(); + + return { + content: [ + { + type: "text", + text: `Listen key deleted successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to delete listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/mark.ts b/src/tools/binance-options/mark.ts index 246e5cde..e3c654da 100644 --- a/src/tools/binance-options/mark.ts +++ b/src/tools/binance-options/mark.ts @@ -1,39 +1,42 @@ // src/tools/binance-options/mark.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsMark(server: McpServer) { - server.tool( - "BinanceOptionsMark", - "Get option mark price for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const data = await optionsClient.mark(params); - - return { - content: [ - { - type: "text", - text: `Option mark price retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get mark price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsMark", + { + description: "Get option mark price for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await optionsClient.mark(params); + + return { + content: [ + { + type: "text", + text: `Option mark price retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get mark price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/newOrder.ts b/src/tools/binance-options/newOrder.ts index 1d15e5b7..0499aa2b 100644 --- a/src/tools/binance-options/newOrder.ts +++ b/src/tools/binance-options/newOrder.ts @@ -1,53 +1,67 @@ // src/tools/binance-options/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsNewOrder(server: McpServer) { - server.tool( - "BinanceOptionsNewOrder", - "Create a new options order.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), - type: z.enum(["LIMIT", "MARKET"]).describe("Order type"), - quantity: z.number().describe("Order quantity"), - price: z.number().optional().describe("Order price (required for LIMIT orders)"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - reduceOnly: z.boolean().optional().describe("Reduce only flag"), - postOnly: z.boolean().optional().describe("Post only flag"), - newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), - clientOrderId: z.string().optional().describe("Client order ID") - }, - async ({ symbol, side, type, quantity, price, timeInForce, reduceOnly, postOnly, newOrderRespType, clientOrderId }) => { - try { - const params: any = { symbol, side, type, quantity }; - if (price !== undefined) params.price = price; - if (timeInForce) params.timeInForce = timeInForce; - if (reduceOnly !== undefined) params.reduceOnly = reduceOnly; - if (postOnly !== undefined) params.postOnly = postOnly; - if (newOrderRespType) params.newOrderRespType = newOrderRespType; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const data = await optionsClient.newOrder(params); - - return { - content: [ - { - type: "text", - text: `Options order created successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsNewOrder", + { + description: "Create a new options order.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), + type: z.enum(["LIMIT", "MARKET"]).describe("Order type"), + quantity: z.number().describe("Order quantity"), + price: z.number().optional().describe("Order price (required for LIMIT orders)"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + reduceOnly: z.boolean().optional().describe("Reduce only flag"), + postOnly: z.boolean().optional().describe("Post only flag"), + newOrderRespType: z.enum(["ACK", "RESULT"]).optional().describe("Response type"), + clientOrderId: z.string().optional().describe("Client order ID"), + }, + }, + async ({ + symbol, + side, + type, + quantity, + price, + timeInForce, + reduceOnly, + postOnly, + newOrderRespType, + clientOrderId, + }) => { + try { + const params: any = { symbol, side, type, quantity }; + if (price !== undefined) params.price = price; + if (timeInForce) params.timeInForce = timeInForce; + if (reduceOnly !== undefined) params.reduceOnly = reduceOnly; + if (postOnly !== undefined) params.postOnly = postOnly; + if (newOrderRespType) params.newOrderRespType = newOrderRespType; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const data = await optionsClient.newOrder(params); + + return { + content: [ + { + type: "text", + text: `Options order created successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/openInterest.ts b/src/tools/binance-options/openInterest.ts index 15fcb372..f1307baf 100644 --- a/src/tools/binance-options/openInterest.ts +++ b/src/tools/binance-options/openInterest.ts @@ -1,39 +1,42 @@ // src/tools/binance-options/openInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsOpenInterest(server: McpServer) { - server.tool( - "BinanceOptionsOpenInterest", - "Get open interest for an option symbol.", - { - underlyingAsset: z.string().describe("Underlying asset (e.g., BTC)"), - expiration: z.string().describe("Expiration date (e.g., 240126)") - }, - async ({ underlyingAsset, expiration }) => { - try { - const params: any = { underlyingAsset, expiration }; - - const data = await optionsClient.openInterest(params); - - return { - content: [ - { - type: "text", - text: `Open interest retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get open interest: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsOpenInterest", + { + description: "Get open interest for an option symbol.", + inputSchema: { + underlyingAsset: z.string().describe("Underlying asset (e.g., BTC)"), + expiration: z.string().describe("Expiration date (e.g., 240126)"), + }, + }, + async ({ underlyingAsset, expiration }) => { + try { + const params: any = { underlyingAsset, expiration }; + + const data = await optionsClient.openInterest(params); + + return { + content: [ + { + type: "text", + text: `Open interest retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open interest: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/openOrders.ts b/src/tools/binance-options/openOrders.ts index dbe87f55..ff937238 100644 --- a/src/tools/binance-options/openOrders.ts +++ b/src/tools/binance-options/openOrders.ts @@ -1,39 +1,42 @@ // src/tools/binance-options/openOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsOpenOrders(server: McpServer) { - server.tool( - "BinanceOptionsOpenOrders", - "Get all open options orders.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const data = await optionsClient.openOrders(params); - - return { - content: [ - { - type: "text", - text: `Open orders retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsOpenOrders", + { + description: "Get all open options orders.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await optionsClient.openOrders(params); + + return { + content: [ + { + type: "text", + text: `Open orders retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/ping.ts b/src/tools/binance-options/ping.ts index 6528deca..1182152a 100644 --- a/src/tools/binance-options/ping.ts +++ b/src/tools/binance-options/ping.ts @@ -1,33 +1,34 @@ // src/tools/binance-options/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsPing(server: McpServer) { - server.tool( - "BinanceOptionsPing", - "Test connectivity to the Binance Options API.", - {}, - async () => { - try { - const data = await optionsClient.ping(); - - return { - content: [ - { - type: "text", - text: `Options API connectivity test successful. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Options API connectivity test failed: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsPing", + { description: "Test connectivity to the Binance Options API." }, + async () => { + try { + const data = await optionsClient.ping(); + + return { + content: [ + { + type: "text", + text: `Options API connectivity test successful. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Options API connectivity test failed: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/position.ts b/src/tools/binance-options/position.ts index 6b24b3bb..d9824bc2 100644 --- a/src/tools/binance-options/position.ts +++ b/src/tools/binance-options/position.ts @@ -1,39 +1,42 @@ // src/tools/binance-options/position.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsPosition(server: McpServer) { - server.tool( - "BinanceOptionsPosition", - "Get current options position information.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const data = await optionsClient.position(params); - - return { - content: [ - { - type: "text", - text: `Position information retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get position: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsPosition", + { + description: "Get current options position information.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await optionsClient.position(params); + + return { + content: [ + { + type: "text", + text: `Position information retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get position: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/ticker.ts b/src/tools/binance-options/ticker.ts index 0c3aa846..fe016183 100644 --- a/src/tools/binance-options/ticker.ts +++ b/src/tools/binance-options/ticker.ts @@ -1,39 +1,42 @@ // src/tools/binance-options/ticker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsTicker(server: McpServer) { - server.tool( - "BinanceOptionsTicker", - "Get 24hr ticker price change statistics for an option symbol.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const data = await optionsClient.ticker(params); - - return { - content: [ - { - type: "text", - text: `24hr ticker statistics retrieved. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsTicker", + { + description: "Get 24hr ticker price change statistics for an option symbol.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const data = await optionsClient.ticker(params); + + return { + content: [ + { + type: "text", + text: `24hr ticker statistics retrieved. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/time.ts b/src/tools/binance-options/time.ts index 10ac4c4d..0211957b 100644 --- a/src/tools/binance-options/time.ts +++ b/src/tools/binance-options/time.ts @@ -1,33 +1,32 @@ // src/tools/binance-options/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsTime(server: McpServer) { - server.tool( - "BinanceOptionsTime", - "Get the current server time from Binance Options API.", - {}, - async () => { - try { - const data = await optionsClient.time(); - - return { - content: [ - { - type: "text", - text: `Server time retrieved successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get server time: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsTime", + { description: "Get the current server time from Binance Options API." }, + async () => { + try { + const data = await optionsClient.time(); + + return { + content: [ + { + type: "text", + text: `Server time retrieved successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/trades.ts b/src/tools/binance-options/trades.ts index e691b67f..fe4cde98 100644 --- a/src/tools/binance-options/trades.ts +++ b/src/tools/binance-options/trades.ts @@ -1,39 +1,43 @@ // src/tools/binance-options/trades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsTrades(server: McpServer) { - server.tool( - "BinanceOptionsTrades", - "Get recent trades for an option symbol.", - { - symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - limit: z.number().optional().describe("Number of trades to return. Default 100; max 500.") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.trades(params); - return { - content: [ - { - type: "text", - text: `Recent trades for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get recent trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsTrades", + { + description: "Get recent trades for an option symbol.", + inputSchema: { + symbol: z.string().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + limit: z.number().optional().describe("Number of trades to return. Default 100; max 500."), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.trades(params); + + return { + content: [ + { + type: "text", + text: `Recent trades for ${symbol}. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get recent trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-options/userTrades.ts b/src/tools/binance-options/userTrades.ts index e36dffc1..7906eb63 100644 --- a/src/tools/binance-options/userTrades.ts +++ b/src/tools/binance-options/userTrades.ts @@ -1,47 +1,50 @@ // src/tools/binance-options/userTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { optionsClient } from "../../config/binanceClient.js"; export function registerBinanceOptionsUserTrades(server: McpServer) { - server.tool( - "BinanceOptionsUserTrades", - "Get options account trade list.", - { - symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), - fromId: z.number().optional().describe("Trade ID to fetch from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of trades to return. Default 100; max 1000.") - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const data = await optionsClient.userTrades(params); - - return { - content: [ - { - type: "text", - text: `User trades retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get user trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceOptionsUserTrades", + { + description: "Get options account trade list.", + inputSchema: { + symbol: z.string().optional().describe("Option trading symbol (e.g., BTC-240126-42000-C)"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of trades to return. Default 100; max 1000."), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const data = await optionsClient.userTrades(params); + + return { + content: [ + { + type: "text", + text: `User trades retrieved. Count: ${Array.isArray(data) ? data.length : 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get user trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-pay/index.ts b/src/tools/binance-pay/index.ts index 9a3bc0a2..5d04881a 100644 --- a/src/tools/binance-pay/index.ts +++ b/src/tools/binance-pay/index.ts @@ -1,7 +1,8 @@ // src/tools/binance-pay/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetPayTradeHistory } from "./pay-api/getPayTradeHistory.js"; export function registerBinancePayTools(server: McpServer) { - registerBinanceGetPayTradeHistory(server); + registerBinanceGetPayTradeHistory(server); } diff --git a/src/tools/binance-pay/pay-api/getPayTradeHistory.ts b/src/tools/binance-pay/pay-api/getPayTradeHistory.ts index d37b514c..4c059bf1 100644 --- a/src/tools/binance-pay/pay-api/getPayTradeHistory.ts +++ b/src/tools/binance-pay/pay-api/getPayTradeHistory.ts @@ -1,54 +1,64 @@ // src/tools/binance-pay/pay-api/getPayTradeHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { payClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { payClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetPayTradeHistory(server: McpServer) { - server.tool( - "BinanceGetPayTradeHistory", + server.registerTool( + "BinanceGetPayTradeHistory", + { + description: "Retrieve Binance Pay trade history using GET to fetch transaction records such as C2C transfers, merchant payments, crypto box activity, refunds, payouts, and remittance details.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - limit: z - .number() - .int() - .max(100, "Limit cannot be greater than 100") - .default(100) - .describe("Number of records to return, default 100, max 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await payClient.restAPI.getPayTradeHistory({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + limit: z + .number() + .int() + .max(100, "Limit cannot be greater than 100") + .default(100) + .describe("Number of records to return, default 100, max 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (payClient as any).restAPI.getPayTradeHistory({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved Binance Pay trade history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved Binance Pay trade history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve Binance Pay trade history: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve Binance Pay trade history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/bnbTransfer.ts b/src/tools/binance-portfolio-margin/bnbTransfer.ts index f815d75d..139f09ff 100644 --- a/src/tools/binance-portfolio-margin/bnbTransfer.ts +++ b/src/tools/binance-portfolio-margin/bnbTransfer.ts @@ -1,41 +1,46 @@ // src/tools/binance-portfolio-margin/bnbTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginBnbTransfer(server: McpServer) { - server.tool( - "BinancePortfolioMarginBnbTransfer", - "Transfer BNB in/out of portfolio margin account.", - { - amount: z.number().describe("Amount of BNB to transfer"), - transferSide: z.enum(["TO_UM", "FROM_UM"]).describe("Transfer direction: TO_UM (to UM account) or FROM_UM (from UM account)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ amount, transferSide, recvWindow }) => { - try { - const params: Record = { amount, transferSide }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.bnbTransfer(params); + server.registerTool( + "BinancePortfolioMarginBnbTransfer", + { + description: "Transfer BNB in/out of portfolio margin account.", + inputSchema: { + amount: z.number().describe("Amount of BNB to transfer"), + transferSide: z + .enum(["TO_UM", "FROM_UM"]) + .describe("Transfer direction: TO_UM (to UM account) or FROM_UM (from UM account)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ amount, transferSide, recvWindow }) => { + try { + const params: Record = { amount, transferSide }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.bnbTransfer(params); + + return { + content: [ + { + type: "text", + text: `BNB transfer completed. Amount: ${amount}, Direction: ${transferSide}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `BNB transfer completed. Amount: ${amount}, Direction: ${transferSide}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to transfer BNB: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to transfer BNB: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/changeAutoRepayFutures.ts b/src/tools/binance-portfolio-margin/changeAutoRepayFutures.ts index 7b3c3715..497bdb44 100644 --- a/src/tools/binance-portfolio-margin/changeAutoRepayFutures.ts +++ b/src/tools/binance-portfolio-margin/changeAutoRepayFutures.ts @@ -1,40 +1,45 @@ // src/tools/binance-portfolio-margin/changeAutoRepayFutures.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginChangeAutoRepayFutures(server: McpServer) { - server.tool( - "BinancePortfolioMarginChangeAutoRepayFutures", - "Change the auto-repay-futures status for portfolio margin account.", - { - autoRepay: z.boolean().describe("Enable or disable auto-repay for futures"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ autoRepay, recvWindow }) => { - try { - const params: Record = { autoRepay }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.changeAutoRepayFutures(params); + server.registerTool( + "BinancePortfolioMarginChangeAutoRepayFutures", + { + description: "Change the auto-repay-futures status for portfolio margin account.", + inputSchema: { + autoRepay: z.boolean().describe("Enable or disable auto-repay for futures"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ autoRepay, recvWindow }) => { + try { + const params: Record = { autoRepay }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.changeAutoRepayFutures(params); + + return { + content: [ + { + type: "text", + text: `Auto-repay-futures status changed to ${autoRepay}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Auto-repay-futures status changed to ${autoRepay}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to change auto-repay-futures status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to change auto-repay-futures status: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/fundAutoCollection.ts b/src/tools/binance-portfolio-margin/fundAutoCollection.ts index c7b8155d..c9047523 100644 --- a/src/tools/binance-portfolio-margin/fundAutoCollection.ts +++ b/src/tools/binance-portfolio-margin/fundAutoCollection.ts @@ -1,39 +1,44 @@ // src/tools/binance-portfolio-margin/fundAutoCollection.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginFundAutoCollection(server: McpServer) { - server.tool( - "BinancePortfolioMarginFundAutoCollection", - "Enable or configure fund auto-collection for portfolio margin account.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.fundAutoCollection(params); + server.registerTool( + "BinancePortfolioMarginFundAutoCollection", + { + description: "Enable or configure fund auto-collection for portfolio margin account.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.fundAutoCollection(params); + + return { + content: [ + { + type: "text", + text: `Fund auto-collection configured. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Fund auto-collection configured. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to configure fund auto-collection: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to configure fund auto-collection: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/fundCollection.ts b/src/tools/binance-portfolio-margin/fundCollection.ts index b88fb70e..c4ee1039 100644 --- a/src/tools/binance-portfolio-margin/fundCollection.ts +++ b/src/tools/binance-portfolio-margin/fundCollection.ts @@ -1,40 +1,43 @@ // src/tools/binance-portfolio-margin/fundCollection.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginFundCollection(server: McpServer) { - server.tool( - "BinancePortfolioMarginFundCollection", - "Trigger fund collection by asset for portfolio margin account.", - { - asset: z.string().describe("Asset symbol to collect (e.g., BTC, USDT)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: Record = { asset }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.fundCollection(params); + server.registerTool( + "BinancePortfolioMarginFundCollection", + { + description: "Trigger fund collection by asset for portfolio margin account.", + inputSchema: { + asset: z.string().describe("Asset symbol to collect (e.g., BTC, USDT)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: Record = { asset }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.fundCollection(params); + + return { + content: [ + { + type: "text", + text: `Fund collection triggered for ${asset}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Fund collection triggered for ${asset}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to trigger fund collection: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to trigger fund collection: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getAccountBalance.ts b/src/tools/binance-portfolio-margin/getAccountBalance.ts index df9e7fcd..a192bc7c 100644 --- a/src/tools/binance-portfolio-margin/getAccountBalance.ts +++ b/src/tools/binance-portfolio-margin/getAccountBalance.ts @@ -1,41 +1,47 @@ // src/tools/binance-portfolio-margin/getAccountBalance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetAccountBalance(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAccountBalance", - "Query portfolio margin account balance.", - { - asset: z.string().optional().describe("Asset symbol (e.g., BTC, USDT). If not provided, returns all assets"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: Record = {}; - if (asset !== undefined) params.asset = asset; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getBalance(params); + server.registerTool( + "BinancePortfolioMarginGetAccountBalance", + { + description: "Query portfolio margin account balance.", + inputSchema: { + asset: z + .string() + .optional() + .describe("Asset symbol (e.g., BTC, USDT). If not provided, returns all assets"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: Record = {}; + if (asset !== undefined) params.asset = asset; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getBalance(params); + + return { + content: [ + { + type: "text", + text: `Retrieved account balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to retrieve account balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getAutoRepayFuturesStatus.ts b/src/tools/binance-portfolio-margin/getAutoRepayFuturesStatus.ts index f21b82ea..f14c372e 100644 --- a/src/tools/binance-portfolio-margin/getAutoRepayFuturesStatus.ts +++ b/src/tools/binance-portfolio-margin/getAutoRepayFuturesStatus.ts @@ -1,39 +1,44 @@ // src/tools/binance-portfolio-margin/getAutoRepayFuturesStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetAutoRepayFuturesStatus(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAutoRepayFuturesStatus", - "Get the current auto-repay-futures status for portfolio margin account.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getAutoRepayFuturesStatus(params); + server.registerTool( + "BinancePortfolioMarginGetAutoRepayFuturesStatus", + { + description: "Get the current auto-repay-futures status for portfolio margin account.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getAutoRepayFuturesStatus(params); + + return { + content: [ + { + type: "text", + text: `Retrieved auto-repay-futures status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved auto-repay-futures status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve auto-repay-futures status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve auto-repay-futures status: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getCollateralRate.ts b/src/tools/binance-portfolio-margin/getCollateralRate.ts index 6808aa27..021c6c5a 100644 --- a/src/tools/binance-portfolio-margin/getCollateralRate.ts +++ b/src/tools/binance-portfolio-margin/getCollateralRate.ts @@ -1,39 +1,42 @@ // src/tools/binance-portfolio-margin/getCollateralRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetCollateralRate(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetCollateralRate", - "Query portfolio margin collateral rate for assets.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getCollateralRate(params); + server.registerTool( + "BinancePortfolioMarginGetCollateralRate", + { + description: "Query portfolio margin collateral rate for assets.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getCollateralRate(params); + + return { + content: [ + { + type: "text", + text: `Retrieved portfolio margin collateral rate. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved portfolio margin collateral rate. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve collateral rate: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to retrieve collateral rate: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getPortfolioMarginAccount.ts b/src/tools/binance-portfolio-margin/getPortfolioMarginAccount.ts index 084c0c19..d5d9c8d0 100644 --- a/src/tools/binance-portfolio-margin/getPortfolioMarginAccount.ts +++ b/src/tools/binance-portfolio-margin/getPortfolioMarginAccount.ts @@ -1,39 +1,45 @@ // src/tools/binance-portfolio-margin/getPortfolioMarginAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetAccount(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAccount", + server.registerTool( + "BinancePortfolioMarginGetAccount", + { + description: "Get portfolio margin account information including account status, balances, and positions.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getAccount(params); + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getAccount(params); + + return { + content: [ + { + type: "text", + text: `Retrieved portfolio margin account info. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved portfolio margin account info. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve portfolio margin account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve portfolio margin account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getPortfolioMarginAssetIndexPrice.ts b/src/tools/binance-portfolio-margin/getPortfolioMarginAssetIndexPrice.ts index c560becb..31704f99 100644 --- a/src/tools/binance-portfolio-margin/getPortfolioMarginAssetIndexPrice.ts +++ b/src/tools/binance-portfolio-margin/getPortfolioMarginAssetIndexPrice.ts @@ -1,41 +1,49 @@ // src/tools/binance-portfolio-margin/getPortfolioMarginAssetIndexPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetAssetIndexPrice(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAssetIndexPrice", - "Query portfolio margin asset index price.", - { - asset: z.string().optional().describe("Asset symbol (e.g., BTC, ETH). If not provided, returns all assets"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: Record = {}; - if (asset !== undefined) params.asset = asset; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getAssetIndexPrice(params); + server.registerTool( + "BinancePortfolioMarginGetAssetIndexPrice", + { + description: "Query portfolio margin asset index price.", + inputSchema: { + asset: z + .string() + .optional() + .describe("Asset symbol (e.g., BTC, ETH). If not provided, returns all assets"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: Record = {}; + if (asset !== undefined) params.asset = asset; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getAssetIndexPrice(params); + + return { + content: [ + { + type: "text", + text: `Retrieved asset index price. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset index price. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset index price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve asset index price: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getPortfolioMarginAssetLeverage.ts b/src/tools/binance-portfolio-margin/getPortfolioMarginAssetLeverage.ts index 5a8e485c..d1d32b4c 100644 --- a/src/tools/binance-portfolio-margin/getPortfolioMarginAssetLeverage.ts +++ b/src/tools/binance-portfolio-margin/getPortfolioMarginAssetLeverage.ts @@ -1,39 +1,42 @@ // src/tools/binance-portfolio-margin/getPortfolioMarginAssetLeverage.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetAssetLeverage(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetAssetLeverage", - "Query portfolio margin asset leverage information.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getAssetLeverage(params); + server.registerTool( + "BinancePortfolioMarginGetAssetLeverage", + { + description: "Query portfolio margin asset leverage information.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getAssetLeverage(params); + + return { + content: [ + { + type: "text", + text: `Retrieved asset leverage information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset leverage information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset leverage: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to retrieve asset leverage: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getPortfolioMarginBankruptcyLoanAmount.ts b/src/tools/binance-portfolio-margin/getPortfolioMarginBankruptcyLoanAmount.ts index 7f907918..602e8b4e 100644 --- a/src/tools/binance-portfolio-margin/getPortfolioMarginBankruptcyLoanAmount.ts +++ b/src/tools/binance-portfolio-margin/getPortfolioMarginBankruptcyLoanAmount.ts @@ -1,39 +1,44 @@ // src/tools/binance-portfolio-margin/getPortfolioMarginBankruptcyLoanAmount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetBankruptcyLoanAmount(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetBankruptcyLoanAmount", - "Query portfolio margin bankruptcy loan amount.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getBankruptcyLoanAmount(params); + server.registerTool( + "BinancePortfolioMarginGetBankruptcyLoanAmount", + { + description: "Query portfolio margin bankruptcy loan amount.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getBankruptcyLoanAmount(params); + + return { + content: [ + { + type: "text", + text: `Retrieved bankruptcy loan amount. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved bankruptcy loan amount. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve bankruptcy loan amount: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve bankruptcy loan amount: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/getPortfolioMarginInterestHistory.ts b/src/tools/binance-portfolio-margin/getPortfolioMarginInterestHistory.ts index 8d9bb36f..2995c77c 100644 --- a/src/tools/binance-portfolio-margin/getPortfolioMarginInterestHistory.ts +++ b/src/tools/binance-portfolio-margin/getPortfolioMarginInterestHistory.ts @@ -1,47 +1,50 @@ // src/tools/binance-portfolio-margin/getPortfolioMarginInterestHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginGetInterestHistory(server: McpServer) { - server.tool( - "BinancePortfolioMarginGetInterestHistory", - "Query portfolio margin interest history.", - { - asset: z.string().optional().describe("Asset symbol (e.g., BTC, USDT)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - size: z.number().optional().describe("Number of results to return, default 10, max 100"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, startTime, endTime, size, recvWindow }) => { - try { - const params: Record = {}; - if (asset !== undefined) params.asset = asset; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (size !== undefined) params.size = size; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.getInterestHistory(params); + server.registerTool( + "BinancePortfolioMarginGetInterestHistory", + { + description: "Query portfolio margin interest history.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol (e.g., BTC, USDT)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + size: z.number().optional().describe("Number of results to return, default 10, max 100"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, startTime, endTime, size, recvWindow }) => { + try { + const params: Record = {}; + if (asset !== undefined) params.asset = asset; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (size !== undefined) params.size = size; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.getInterestHistory(params); + + return { + content: [ + { + type: "text", + text: `Retrieved interest history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved interest history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve interest history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to retrieve interest history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/index.ts b/src/tools/binance-portfolio-margin/index.ts index 48b65b97..ff02d9aa 100644 --- a/src/tools/binance-portfolio-margin/index.ts +++ b/src/tools/binance-portfolio-margin/index.ts @@ -1,40 +1,41 @@ // src/tools/binance-portfolio-margin/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinancePortfolioMarginGetAccount } from "./getPortfolioMarginAccount.js"; -import { registerBinancePortfolioMarginGetCollateralRate } from "./getCollateralRate.js"; -import { registerBinancePortfolioMarginGetBankruptcyLoanAmount } from "./getPortfolioMarginBankruptcyLoanAmount.js"; -import { registerBinancePortfolioMarginRepayBankruptcyLoan } from "./repayPortfolioMarginBankruptcyLoan.js"; -import { registerBinancePortfolioMarginGetInterestHistory } from "./getPortfolioMarginInterestHistory.js"; -import { registerBinancePortfolioMarginGetAssetIndexPrice } from "./getPortfolioMarginAssetIndexPrice.js"; -import { registerBinancePortfolioMarginFundAutoCollection } from "./fundAutoCollection.js"; -import { registerBinancePortfolioMarginFundCollection } from "./fundCollection.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinancePortfolioMarginBnbTransfer } from "./bnbTransfer.js"; import { registerBinancePortfolioMarginChangeAutoRepayFutures } from "./changeAutoRepayFutures.js"; +import { registerBinancePortfolioMarginFundAutoCollection } from "./fundAutoCollection.js"; +import { registerBinancePortfolioMarginFundCollection } from "./fundCollection.js"; +import { registerBinancePortfolioMarginGetAccountBalance } from "./getAccountBalance.js"; import { registerBinancePortfolioMarginGetAutoRepayFuturesStatus } from "./getAutoRepayFuturesStatus.js"; -import { registerBinancePortfolioMarginRepayFuturesNegativeBalance } from "./repayFuturesNegativeBalance.js"; +import { registerBinancePortfolioMarginGetCollateralRate } from "./getCollateralRate.js"; +import { registerBinancePortfolioMarginGetAccount } from "./getPortfolioMarginAccount.js"; +import { registerBinancePortfolioMarginGetAssetIndexPrice } from "./getPortfolioMarginAssetIndexPrice.js"; import { registerBinancePortfolioMarginGetAssetLeverage } from "./getPortfolioMarginAssetLeverage.js"; -import { registerBinancePortfolioMarginGetAccountBalance } from "./getAccountBalance.js"; +import { registerBinancePortfolioMarginGetBankruptcyLoanAmount } from "./getPortfolioMarginBankruptcyLoanAmount.js"; +import { registerBinancePortfolioMarginGetInterestHistory } from "./getPortfolioMarginInterestHistory.js"; +import { registerBinancePortfolioMarginRepayFuturesNegativeBalance } from "./repayFuturesNegativeBalance.js"; +import { registerBinancePortfolioMarginRepayBankruptcyLoan } from "./repayPortfolioMarginBankruptcyLoan.js"; export function registerBinancePortfolioMarginTools(server: McpServer) { - // Account Information - registerBinancePortfolioMarginGetAccount(server); - registerBinancePortfolioMarginGetAccountBalance(server); - registerBinancePortfolioMarginGetCollateralRate(server); - registerBinancePortfolioMarginGetAssetLeverage(server); - registerBinancePortfolioMarginGetAssetIndexPrice(server); - - // Interest & Loan Management - registerBinancePortfolioMarginGetInterestHistory(server); - registerBinancePortfolioMarginGetBankruptcyLoanAmount(server); - registerBinancePortfolioMarginRepayBankruptcyLoan(server); - - // Fund Management - registerBinancePortfolioMarginFundAutoCollection(server); - registerBinancePortfolioMarginFundCollection(server); - registerBinancePortfolioMarginBnbTransfer(server); - - // Futures Auto-Repay - registerBinancePortfolioMarginChangeAutoRepayFutures(server); - registerBinancePortfolioMarginGetAutoRepayFuturesStatus(server); - registerBinancePortfolioMarginRepayFuturesNegativeBalance(server); + // Account Information + registerBinancePortfolioMarginGetAccount(server); + registerBinancePortfolioMarginGetAccountBalance(server); + registerBinancePortfolioMarginGetCollateralRate(server); + registerBinancePortfolioMarginGetAssetLeverage(server); + registerBinancePortfolioMarginGetAssetIndexPrice(server); + + // Interest & Loan Management + registerBinancePortfolioMarginGetInterestHistory(server); + registerBinancePortfolioMarginGetBankruptcyLoanAmount(server); + registerBinancePortfolioMarginRepayBankruptcyLoan(server); + + // Fund Management + registerBinancePortfolioMarginFundAutoCollection(server); + registerBinancePortfolioMarginFundCollection(server); + registerBinancePortfolioMarginBnbTransfer(server); + + // Futures Auto-Repay + registerBinancePortfolioMarginChangeAutoRepayFutures(server); + registerBinancePortfolioMarginGetAutoRepayFuturesStatus(server); + registerBinancePortfolioMarginRepayFuturesNegativeBalance(server); } diff --git a/src/tools/binance-portfolio-margin/repayFuturesNegativeBalance.ts b/src/tools/binance-portfolio-margin/repayFuturesNegativeBalance.ts index ea8c69e1..1937098d 100644 --- a/src/tools/binance-portfolio-margin/repayFuturesNegativeBalance.ts +++ b/src/tools/binance-portfolio-margin/repayFuturesNegativeBalance.ts @@ -1,39 +1,44 @@ // src/tools/binance-portfolio-margin/repayFuturesNegativeBalance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginRepayFuturesNegativeBalance(server: McpServer) { - server.tool( - "BinancePortfolioMarginRepayFuturesNegativeBalance", - "Repay futures negative balance for portfolio margin account.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.repayFuturesNegativeBalance(params); + server.registerTool( + "BinancePortfolioMarginRepayFuturesNegativeBalance", + { + description: "Repay futures negative balance for portfolio margin account.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.repayFuturesNegativeBalance(params); + + return { + content: [ + { + type: "text", + text: `Futures negative balance repaid. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Futures negative balance repaid. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to repay futures negative balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to repay futures negative balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-portfolio-margin/repayPortfolioMarginBankruptcyLoan.ts b/src/tools/binance-portfolio-margin/repayPortfolioMarginBankruptcyLoan.ts index 0dedd7ed..72fed32c 100644 --- a/src/tools/binance-portfolio-margin/repayPortfolioMarginBankruptcyLoan.ts +++ b/src/tools/binance-portfolio-margin/repayPortfolioMarginBankruptcyLoan.ts @@ -1,39 +1,42 @@ // src/tools/binance-portfolio-margin/repayPortfolioMarginBankruptcyLoan.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { portfolioMarginClient } from "../../config/binanceClient.js"; export function registerBinancePortfolioMarginRepayBankruptcyLoan(server: McpServer) { - server.tool( - "BinancePortfolioMarginRepayBankruptcyLoan", - "Repay portfolio margin bankruptcy loan.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await portfolioMarginClient.repayBankruptcyLoan(params); + server.registerTool( + "BinancePortfolioMarginRepayBankruptcyLoan", + { + description: "Repay portfolio margin bankruptcy loan.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await portfolioMarginClient.repayBankruptcyLoan(params); + + return { + content: [ + { + type: "text", + text: `Successfully repaid bankruptcy loan. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully repaid bankruptcy loan. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to repay bankruptcy loan: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to repay bankruptcy loan: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-rebate/index.ts b/src/tools/binance-rebate/index.ts index 300e0450..7a07677c 100644 --- a/src/tools/binance-rebate/index.ts +++ b/src/tools/binance-rebate/index.ts @@ -1,7 +1,8 @@ // src/tools/binance-rebate/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetSpotRebateHistoryRecords } from "./rebate-api/getSpotRebateHistoryRecords.js"; export function registerBinanceRebateTools(server: McpServer) { - registerBinanceGetSpotRebateHistoryRecords(server); + registerBinanceGetSpotRebateHistoryRecords(server); } diff --git a/src/tools/binance-rebate/rebate-api/getSpotRebateHistoryRecords.ts b/src/tools/binance-rebate/rebate-api/getSpotRebateHistoryRecords.ts index c3b46ee8..cc36b657 100644 --- a/src/tools/binance-rebate/rebate-api/getSpotRebateHistoryRecords.ts +++ b/src/tools/binance-rebate/rebate-api/getSpotRebateHistoryRecords.ts @@ -1,51 +1,61 @@ // src/tools/binance-pay/rebate-api/getSpotRebateHistoryRecords.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { rebateClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { rebateClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSpotRebateHistoryRecords(server: McpServer) { - server.tool( - "BinanceGetSpotRebateHistoryRecords", + server.registerTool( + "BinanceGetSpotRebateHistoryRecords", + { + description: "Retrieve the history of spot rebate records, including commission rebates and referral kickbacks, for the past 7 days or a custom date range (within 30 days).", - { - startTime: z.number().int().optional().describe("Start time in milliseconds"), - endTime: z.number().int().optional().describe("End time in milliseconds"), - page: z.number().int().default(1).describe("Page number, default is 1"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await rebateClient.restAPI.getSpotRebateHistoryRecords({ - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds"), + endTime: z.number().int().optional().describe("End time in milliseconds"), + page: z.number().int().default(1).describe("Page number, default is 1"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await rebateClient.restAPI.getSpotRebateHistoryRecords({ + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the history of spot rebate records, including commission rebates and referral kickbacks. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the history of spot rebate records, including commission rebates and referral kickbacks. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the history of spot rebate records: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the history of spot rebate records: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts b/src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts index df77fa91..86d13d83 100644 --- a/src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts +++ b/src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts @@ -1,59 +1,72 @@ // src/tools/binance-simple-earn/account-api/getFlexibleProductPosition.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetFlexibleProductPosition(server: McpServer) { - server.tool( - "BinanceGetFlexibleProductPosition", + server.registerTool( + "BinanceGetFlexibleProductPosition", + { + description: "Fetch your current holdings in Simple Earn Flexible Products, including total amount, reward rates, and redeem status.", - { - asset: z.string().optional().describe("Asset symbol (optional)"), - productId: z.string().optional().describe("Product ID (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying the page. Starts from 1. Default: 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getFlexibleProductPosition({ - ...(params.asset && { asset: params.asset }), - ...(params.productId && { productId: params.productId }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Asset symbol (optional)"), + productId: z.string().optional().describe("Product ID (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying the page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Page size. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getFlexibleProductPosition({ + ...(params.asset && { asset: params.asset }), + ...(params.productId && { productId: params.productId }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully fetched your current holdings in Simple Earn Flexible Products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully fetched your current holdings in Simple Earn Flexible Products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to fetch your current holdings in Simple Earn Flexible Products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to fetch your current holdings in Simple Earn Flexible Products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-simple-earn/account-api/index.ts b/src/tools/binance-simple-earn/account-api/index.ts index 530448c0..ce694ad7 100644 --- a/src/tools/binance-simple-earn/account-api/index.ts +++ b/src/tools/binance-simple-earn/account-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-simple-earn/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSimpleEarnFlexibleProductList } from "./simpleEarnFlexibleProductList.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetFlexibleProductPosition } from "./getFlexibleProductPosition.js"; +import { registerBinanceSimpleEarnFlexibleProductList } from "./simpleEarnFlexibleProductList.js"; export function registerBinanceSimpleEarnAccountApiTools(server: McpServer) { - // Registers a tool to get the list of flexible earning products - registerBinanceSimpleEarnFlexibleProductList(server); + // Registers a tool to get the list of flexible earning products + registerBinanceSimpleEarnFlexibleProductList(server); - // Registers a tool to get the user's position in flexible earning products - registerBinanceGetFlexibleProductPosition(server); + // Registers a tool to get the user's position in flexible earning products + registerBinanceGetFlexibleProductPosition(server); } diff --git a/src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts b/src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts index 70fd0e68..eef70a29 100644 --- a/src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts +++ b/src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts @@ -1,57 +1,70 @@ // src/tools/binance-simple-earn/account-api/simpleEarnFlexibleProductList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceSimpleEarnFlexibleProductList(server: McpServer) { - server.tool( - "BinanceSimpleEarnFlexibleProductList", + server.registerTool( + "BinanceSimpleEarnFlexibleProductList", + { + description: "Retrieve a list of available Simple Earn Flexible Products, including details like APR, purchase status, and subscription limits.", - { - asset: z.string().optional().describe("Asset symbol (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Starts from 1. Default: 1"), - size: z.number().int().min(1).max(100).default(10).optional().describe("Page size. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.getSimpleEarnFlexibleProductList({ - ...(params.asset && { asset: params.asset }), - ...(params.current && { current: params.current }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Asset symbol (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Page size. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.getSimpleEarnFlexibleProductList({ + ...(params.asset && { asset: params.asset }), + ...(params.current && { current: params.current }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve a list of available Simple Earn Flexible Products. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve a list of available Simple Earn Flexible Products. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve a list of available Simple Earn Flexible Products: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve a list of available Simple Earn Flexible Products: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-simple-earn/earn-api/index.ts b/src/tools/binance-simple-earn/earn-api/index.ts index 7d2a23e0..3c1f18b4 100644 --- a/src/tools/binance-simple-earn/earn-api/index.ts +++ b/src/tools/binance-simple-earn/earn-api/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-simple-earn/earn-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubscribeFlexibleProduct } from "./subscribeFlexibleProduct.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceRedeemFlexibleProduct } from "./redeemFlexibleProduct.js"; +import { registerBinanceSubscribeFlexibleProduct } from "./subscribeFlexibleProduct.js"; export function registerBinanceSimpleEarnApiTools(server: McpServer) { - // Register the route for subscribing to a flexible earn product - registerBinanceSubscribeFlexibleProduct(server); + // Register the route for subscribing to a flexible earn product + registerBinanceSubscribeFlexibleProduct(server); - // Register the route for redeeming from a flexible earn product - registerBinanceRedeemFlexibleProduct(server); + // Register the route for redeeming from a flexible earn product + registerBinanceRedeemFlexibleProduct(server); } diff --git a/src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts b/src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts index 13f0fd16..ba5f2754 100644 --- a/src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts +++ b/src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts @@ -1,71 +1,81 @@ // src/tools/binance-simple-earn/earn-api/redeemFlexibleProduct.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemFlexibleProduct(server: McpServer) { - server.tool( - "BinanceRedeemFlexibleProduct", + server.registerTool( + "BinanceRedeemFlexibleProduct", + { + description: "Allows users to redeem their funds from a Flexible Earn investment product using a programmatic HTTP POST request.", - { - productId: z.string().describe("Product ID"), - redeemAll: z.boolean().optional().describe("true or false, default to false"), - amount: z.number().positive().optional().describe("If redeemAll is false, amount is mandatory"), - destAccount: z - .enum(["SPOT", "FUND"]) - .optional() - .describe("Destination account: SPOT or FUND; default is SPOT"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const { productId, redeemAll = false, amount, destAccount, recvWindow } = params; + inputSchema: { + productId: z.string().describe("Product ID"), + redeemAll: z.boolean().optional().describe("true or false, default to false"), + amount: z + .number() + .positive() + .optional() + .describe("If redeemAll is false, amount is mandatory"), + destAccount: z + .enum(["SPOT", "FUND"]) + .optional() + .describe("Destination account: SPOT or FUND; default is SPOT"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const { productId, redeemAll = false, amount, destAccount, recvWindow } = params; - // Defensive check - if (!redeemAll && (amount === undefined || amount <= 0)) { - return { - content: [ - { - type: "text", - text: "You must provide a valid amount when redeemAll is false." - } - ], - isError: true - }; - } + // Defensive check + if (!redeemAll && (amount === undefined || amount <= 0)) { + return { + content: [ + { + type: "text", + text: "You must provide a valid amount when redeemAll is false.", + }, + ], + isError: true, + }; + } - const response = await simpleEarnClient.restAPI.redeemFlexibleProduct({ - productId, - ...(redeemAll !== undefined && { redeemAll }), - ...(amount !== undefined && { amount }), - ...(destAccount && { destAccount }), - ...(recvWindow && { recvWindow }) - }); + const response = await (simpleEarnClient as any).restAPI.redeemFlexibleProduct({ + productId, + ...(redeemAll !== undefined && { redeemAll }), + ...(amount !== undefined && { amount }), + ...(destAccount && { destAccount }), + ...(recvWindow && { recvWindow }), + }); - const data = await response.data(); + const data = await response.data(); - return { - content: [ - { - type: "text", - text: `Successfully redeem funds from a flexible earn investment. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to allows users to redeem their funds from a Flexible Earn investment: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Successfully redeem funds from a flexible earn investment. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { + type: "text", + text: `Failed to allows users to redeem their funds from a Flexible Earn investment: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts b/src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts index 5ec0a898..eb961569 100644 --- a/src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts +++ b/src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts @@ -1,56 +1,62 @@ // src/tools/binance-simple-earn/earn-api/subscribeFlexibleProduct.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { simpleEarnClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { simpleEarnClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeFlexibleProduct(server: McpServer) { - server.tool( - "BinanceSubscribeFlexibleProduct", + server.registerTool( + "BinanceSubscribeFlexibleProduct", + { + description: "Subscribe to a Simple Earn Flexible Product by specifying the product ID and amount. Optional parameters include auto-subscribe and source account. ", - { - productId: z.string().describe("Product ID"), - amount: z.number().positive().describe("Amount to purchase"), - autoSubscribe: z.boolean().optional().describe("true or false, default is true"), - sourceAccount: z - .enum(["SPOT", "FUND", "ALL"]) - .optional() - .describe("Source account: SPOT, FUND, or ALL; default is SPOT"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await simpleEarnClient.restAPI.subscribeFlexibleProduct({ - productId: params.productId, - amount: params.amount, - ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), - ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + productId: z.string().describe("Product ID"), + amount: z.number().positive().describe("Amount to purchase"), + autoSubscribe: z.boolean().optional().describe("true or false, default is true"), + sourceAccount: z + .enum(["SPOT", "FUND", "ALL"]) + .optional() + .describe("Source account: SPOT, FUND, or ALL; default is SPOT"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await (simpleEarnClient as any).restAPI.subscribeFlexibleProduct({ + productId: params.productId, + amount: params.amount, + ...(params.autoSubscribe !== undefined && { autoSubscribe: params.autoSubscribe }), + ...(params.sourceAccount && { sourceAccount: params.sourceAccount }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully Subscribed to Simple Earn Flexible Product id ${ + params.productId + } and amount${params.amount}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully Subscribed to Simple Earn Flexible Product id ${ - params.productId - } and amount${params.amount}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to subscribe to a Simple Earn Flexible Product: ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to subscribe to a Simple Earn Flexible Product: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-simple-earn/index.ts b/src/tools/binance-simple-earn/index.ts index af82b8ee..948d3dbb 100644 --- a/src/tools/binance-simple-earn/index.ts +++ b/src/tools/binance-simple-earn/index.ts @@ -1,12 +1,13 @@ // src/tools/binance-simple-earn/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSimpleEarnApiTools } from "./earn-api/index.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSimpleEarnAccountApiTools } from "./account-api/index.js"; +import { registerBinanceSimpleEarnApiTools } from "./earn-api/index.js"; export function registerBinanceSimpleEarnTools(server: McpServer) { - // Registers core API tools like subscribing to flexible products - registerBinanceSimpleEarnApiTools(server); + // Registers core API tools like subscribing to flexible products + registerBinanceSimpleEarnApiTools(server); - // Registers account-related tools like viewing product lists and positions - registerBinanceSimpleEarnAccountApiTools(server); + // Registers account-related tools like viewing product lists and positions + registerBinanceSimpleEarnAccountApiTools(server); } diff --git a/src/tools/binance-spot/account-api/accountCommission.ts b/src/tools/binance-spot/account-api/accountCommission.ts index 399bebdd..174c56f7 100644 --- a/src/tools/binance-spot/account-api/accountCommission.ts +++ b/src/tools/binance-spot/account-api/accountCommission.ts @@ -1,43 +1,47 @@ // src/tools/binance-spot/account-api/accountCommission.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAccountCommission(server: McpServer) { - server.tool( - "BinanceAccountCommission", - "Get account commission rates for a specific symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, recvWindow }) => { - try { - const params: any = { symbol }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.accountCommission(params); + server.registerTool( + "BinanceAccountCommission", + { + description: "Get account commission rates for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, recvWindow }) => { + try { + const params: any = { symbol }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.accountCommission(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved account commission rates for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account commission rates for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account commission rates: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve account commission rates: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/account-api/getAccount.ts b/src/tools/binance-spot/account-api/getAccount.ts index c1339fa9..4de06d52 100644 --- a/src/tools/binance-spot/account-api/getAccount.ts +++ b/src/tools/binance-spot/account-api/getAccount.ts @@ -1,42 +1,51 @@ -// src/tools/binance-spot/account-api/getAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { JSONStringify } from "json-with-bigint"; import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetAccount(server: McpServer) { - server.tool( - "BinanceGetAccount", - "Get current account information.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.getAccount(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved account information. Account contains ${data.balances?.length || 0} balances. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceGetAccount", + { + description: "Get current account information.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = { + omitZeroBalances: true, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.getAccount(params); + + const data = await response.data(); + + // This `content` is the CallToolResult payload: it flows up through McpServer → Server → Protocol + // and is sent to the client via transport.send(). When using SSE, see server/sse.ts for logging. + const content = [ + { + type: "text" as const, + text: `Retrieved account information. Account contains ${data.balances?.length || 0} balances. Response: ${JSONStringify(data)}`, + }, + ]; + console.log("[MCP tool BinanceGetAccount] returning content (length)", content.length); + + return { content }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve account information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/account-api/index.ts b/src/tools/binance-spot/account-api/index.ts index 6b1c4c10..53d31c2c 100644 --- a/src/tools/binance-spot/account-api/index.ts +++ b/src/tools/binance-spot/account-api/index.ts @@ -1,17 +1,18 @@ // src/tools/binance-spot/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceMyPreventedMatches } from "./myPreventedMatches.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountCommission } from "./accountCommission.js"; import { registerBinanceGetAccount } from "./getAccount.js"; import { registerBinanceMyAllocations } from "./myAllocations.js"; -import { registerBinanceRateLimitOrder } from "./rateLimitOrder.js"; -import { registerBinanceAccountCommission } from "./accountCommission.js"; +import { registerBinanceMyPreventedMatches } from "./myPreventedMatches.js"; import { registerBinanceMyTrades } from "./myTrades.js"; +import { registerBinanceRateLimitOrder } from "./rateLimitOrder.js"; export function registerBinanceAccountApiTools(server: McpServer) { - registerBinanceMyPreventedMatches(server); - registerBinanceGetAccount(server); - registerBinanceMyAllocations(server); - registerBinanceRateLimitOrder(server); - registerBinanceAccountCommission(server); - registerBinanceMyTrades(server); + registerBinanceMyPreventedMatches(server); + registerBinanceGetAccount(server); + registerBinanceMyAllocations(server); + registerBinanceRateLimitOrder(server); + registerBinanceAccountCommission(server); + registerBinanceMyTrades(server); } diff --git a/src/tools/binance-spot/account-api/myAllocations.ts b/src/tools/binance-spot/account-api/myAllocations.ts index 9d2bde83..672f5b92 100644 --- a/src/tools/binance-spot/account-api/myAllocations.ts +++ b/src/tools/binance-spot/account-api/myAllocations.ts @@ -1,52 +1,54 @@ // src/tools/binance-spot/account-api/myAllocations.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyAllocations(server: McpServer) { - server.tool( - "BinanceMyAllocations", - "Get SOR allocations for Self-Trade Prevention.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - allocationId: z.number().optional().describe("Allocation ID"), - orderId: z.number().optional().describe("Order ID"), - fromAllocationId: z.number().optional().describe("Allocation ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, allocationId, orderId, fromAllocationId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (allocationId !== undefined) params.allocationId = allocationId; - if (orderId !== undefined) params.orderId = orderId; - if (fromAllocationId !== undefined) params.fromAllocationId = fromAllocationId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myAllocations(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved SOR allocations for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve SOR allocations: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyAllocations", + { + description: "Get SOR allocations for Self-Trade Prevention.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + allocationId: z.number().optional().describe("Allocation ID"), + orderId: z.number().optional().describe("Order ID"), + fromAllocationId: z.number().optional().describe("Allocation ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, allocationId, orderId, fromAllocationId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (allocationId !== undefined) params.allocationId = allocationId; + if (orderId !== undefined) params.orderId = orderId; + if (fromAllocationId !== undefined) params.fromAllocationId = fromAllocationId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myAllocations(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved SOR allocations for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve SOR allocations: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/account-api/myPreventedMatches.ts b/src/tools/binance-spot/account-api/myPreventedMatches.ts index c1ed4732..cb6e5e41 100644 --- a/src/tools/binance-spot/account-api/myPreventedMatches.ts +++ b/src/tools/binance-spot/account-api/myPreventedMatches.ts @@ -1,51 +1,56 @@ // src/tools/binance-spot/account-api/myPreventedMatches.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyPreventedMatches(server: McpServer) { - server.tool( - "BinanceMyPreventedMatches", - "Get prevented matches for Self-Trade Prevention.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - preventedMatchId: z.number().optional().describe("Prevented match ID"), - orderId: z.number().optional().describe("Order ID"), - fromPreventedMatchId: z.number().optional().describe("Prevented match ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, preventedMatchId, orderId, fromPreventedMatchId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (preventedMatchId !== undefined) params.preventedMatchId = preventedMatchId; - if (orderId !== undefined) params.orderId = orderId; - if (fromPreventedMatchId !== undefined) params.fromPreventedMatchId = fromPreventedMatchId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myPreventedMatches(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved prevented matches for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve prevented matches: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyPreventedMatches", + { + description: "Get prevented matches for Self-Trade Prevention.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + preventedMatchId: z.number().optional().describe("Prevented match ID"), + orderId: z.number().optional().describe("Order ID"), + fromPreventedMatchId: z.number().optional().describe("Prevented match ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, preventedMatchId, orderId, fromPreventedMatchId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (preventedMatchId !== undefined) params.preventedMatchId = preventedMatchId; + if (orderId !== undefined) params.orderId = orderId; + if (fromPreventedMatchId !== undefined) params.fromPreventedMatchId = fromPreventedMatchId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myPreventedMatches(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved prevented matches for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve prevented matches: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/account-api/myTrades.ts b/src/tools/binance-spot/account-api/myTrades.ts index 450ffd23..9965ad2d 100644 --- a/src/tools/binance-spot/account-api/myTrades.ts +++ b/src/tools/binance-spot/account-api/myTrades.ts @@ -1,54 +1,56 @@ // src/tools/binance-spot/account-api/myTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceMyTrades(server: McpServer) { - server.tool( - "BinanceMyTrades", - "Get trades for a specific account and symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - fromId: z.number().optional().describe("Trade ID to fetch from"), - limit: z.number().optional().describe("Default 500; max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { - try { - const params: any = { symbol }; - - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (fromId !== undefined) params.fromId = fromId; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.myTrades(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + server.registerTool( + "BinanceMyTrades", + { + description: "Get trades for a specific account and symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + limit: z.number().optional().describe("Default 500; max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, orderId, startTime, endTime, fromId, limit, recvWindow }) => { + try { + const params: any = { symbol }; + + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (fromId !== undefined) params.fromId = fromId; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.myTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve account trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/account-api/rateLimitOrder.ts b/src/tools/binance-spot/account-api/rateLimitOrder.ts index a7886d3e..7eabceb3 100644 --- a/src/tools/binance-spot/account-api/rateLimitOrder.ts +++ b/src/tools/binance-spot/account-api/rateLimitOrder.ts @@ -1,42 +1,46 @@ // src/tools/binance-spot/account-api/rateLimitOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceRateLimitOrder(server: McpServer) { - server.tool( - "BinanceRateLimitOrder", - "Get current order count usage for each rate limit.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await spotClient.restAPI.rateLimitOrder(params); + server.registerTool( + "BinanceRateLimitOrder", + { + description: "Get current order count usage for each rate limit.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (spotClient as any).restAPI.rateLimitOrder(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved current order count usage. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved current order count usage. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order count usage: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to retrieve order count usage: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/general-api/exchangeInfo.ts b/src/tools/binance-spot/general-api/exchangeInfo.ts index 0c869f15..2213fa1c 100644 --- a/src/tools/binance-spot/general-api/exchangeInfo.ts +++ b/src/tools/binance-spot/general-api/exchangeInfo.ts @@ -1,49 +1,69 @@ // src/tools/binance-spot/general-api/exchangeInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceExchangeInfo(server: McpServer) { - server.tool( - "BinanceExchangeInfo", - "Get exchange information including rate limits, symbol configs, etc.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - symbols: z.array(z.string()).optional().describe("Array of symbols to get info for"), - permissions: z.array(z.string()).optional().describe("Array of permissions to filter by") - }, - async ({ symbol, symbols, permissions }) => { - try { - const params: any = {}; - - if (symbol) params.symbol = symbol; - if (symbols) params.symbols = symbols; - if (permissions) params.permissions = permissions; - - const response = await spotClient.restAPI.exchangeInfo(params); - - const data = await response.data(); - - const symbolCount = data.symbols?.length || 0; - const exchangeFiltersCount = data.exchangeFilters?.length || 0; - - return { - content: [ - { - type: "text", - text: `Retrieved exchange information. Total symbols: ${symbolCount}, Exchange filters: ${exchangeFiltersCount}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve exchange information: ${errorMessage}` } - ], - isError: true - }; - } + server.registerTool( + "BinanceExchangeInfo", + { + description: "Get exchange information including rate limits, symbol configs, etc.", + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Single trading pair in UPPERCASE, no separators (e.g. BTCUSDT, SOLUSDT). Use this for one pair; do not use both symbol and symbols.", + ), + symbols: z + .array(z.string()) + .optional() + .describe( + 'Multiple pairs as array; each symbol UPPERCASE (e.g. ["BTCUSDT","ETHUSDT"]). Do not use with symbol.', + ), + permissions: z.array(z.string()).optional().describe("Array of permissions to filter by"), + }, + }, + async ({ symbol, symbols, permissions }) => { + try { + const params: Record = {}; + + if (symbol) params.symbol = symbol.toUpperCase(); + if (symbols?.length) { + // Binance expects symbols as a JSON string; symbols must be UPPERCASE (legal range: [^a-z]). + params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); } - ); + // Only send permissions when not filtering by symbol(s); API rejects "permissions" when symbol/symbols are present. + if (permissions?.length && !params.symbol && !params.symbols) + params.permissions = permissions; + + const response = await (spotClient as any).restAPI.exchangeInfo(params); + + const data = await response.data(); + + const symbolCount = data.symbols?.length || 0; + const exchangeFiltersCount = data.exchangeFilters?.length || 0; + + return { + content: [ + { + type: "text", + text: `Retrieved exchange information. Total symbols: ${symbolCount}, Exchange filters: ${exchangeFiltersCount}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve exchange information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/general-api/index.ts b/src/tools/binance-spot/general-api/index.ts index 5ba8ee07..3cecf4b7 100644 --- a/src/tools/binance-spot/general-api/index.ts +++ b/src/tools/binance-spot/general-api/index.ts @@ -1,12 +1,12 @@ // src/tools/binance-spot/general-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceExchangeInfo } from "./exchangeInfo.js"; import { registerBinancePing } from "./ping.js"; import { registerBinanceTime } from "./time.js"; -import { registerBinanceExchangeInfo } from "./exchangeInfo.js"; export function registerBinanceGeneralApiTools(server: McpServer) { - registerBinancePing(server); - registerBinanceTime(server); - registerBinanceExchangeInfo(server); - + registerBinancePing(server); + registerBinanceTime(server); + registerBinanceExchangeInfo(server); } diff --git a/src/tools/binance-spot/general-api/ping.ts b/src/tools/binance-spot/general-api/ping.ts index ee57842a..18939f88 100644 --- a/src/tools/binance-spot/general-api/ping.ts +++ b/src/tools/binance-spot/general-api/ping.ts @@ -1,37 +1,34 @@ // src/tools/binance-spot/general-api/ping.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinancePing(server: McpServer) { - server.tool( - "BinancePing", - "Test connectivity to the Binance API.", - {}, - async () => { - try { - const response = await spotClient.restAPI.ping(); + server.registerTool( + "BinancePing", + { description: "Test connectivity to the Binance API." }, + async () => { + try { + const response = await (spotClient as any).restAPI.ping(); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully pinged Binance API. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully pinged Binance API. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to ping Binance API: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to ping Binance API: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/general-api/time.ts b/src/tools/binance-spot/general-api/time.ts index cd6b4d18..bef51db8 100644 --- a/src/tools/binance-spot/general-api/time.ts +++ b/src/tools/binance-spot/general-api/time.ts @@ -1,34 +1,38 @@ // src/tools/binance-spot/general-api/time.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTime(server: McpServer) { - server.tool("BinanceTime", "Get the current server time from Binance API.", {}, async () => { - try { - const response = await spotClient.restAPI.time(); + server.registerTool( + "BinanceTime", + { description: "Get the current server time from Binance API." }, + async () => { + try { + const response = await (spotClient as any).restAPI.time(); + + const data = await response.data(); + + const serverTime = new Date(data.serverTime).toISOString(); - const data = await response.data(); - - //@ts-ignore - const serverTime = new Date(data.serverTime).toISOString(); + return { + content: [ + { + type: "text", + text: `Current Binance server time: ${serverTime} (${ + data.serverTime + }). Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Current Binance server time: ${serverTime} (${ - data.serverTime - }). Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to retrieve server time: ${errorMessage}` }], - isError: true - }; - } - }); + return { + content: [{ type: "text", text: `Failed to retrieve server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/index.ts b/src/tools/binance-spot/index.ts index d39d3129..16f9345b 100644 --- a/src/tools/binance-spot/index.ts +++ b/src/tools/binance-spot/index.ts @@ -1,25 +1,25 @@ // src/tools/binance-spot/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAccountApiTools } from "./account-api/index.js"; +import { registerBinanceGeneralApiTools } from "./general-api/index.js"; import { registerBinanceMarketApiTools } from "./market-api/index.js"; import { registerBinanceTradeApiTools } from "./trade-api/index.js"; -import { registerBinanceAccountApiTools } from "./account-api/index.js"; import { registerBinanceUserDataStreamApiTools } from "./userdatastream-api/index.js"; -import { registerBinanceGeneralApiTools } from "./general-api/index.js"; export function registerBinanceSpotTools(server: McpServer) { - // Trade API tools - registerBinanceTradeApiTools(server); - - // Market API tools - registerBinanceMarketApiTools(server); - - // Account API tools - registerBinanceAccountApiTools(server); - - // User Data Stream API tools - registerBinanceUserDataStreamApiTools(server); - - // General API tools - registerBinanceGeneralApiTools(server); - + // Trade API tools + registerBinanceTradeApiTools(server); + + // Market API tools + registerBinanceMarketApiTools(server); + + // Account API tools + registerBinanceAccountApiTools(server); + + // User Data Stream API tools + registerBinanceUserDataStreamApiTools(server); + + // General API tools + registerBinanceGeneralApiTools(server); } diff --git a/src/tools/binance-spot/market-api/aggTrades.ts b/src/tools/binance-spot/market-api/aggTrades.ts index 8c14bed9..1d1ef133 100644 --- a/src/tools/binance-spot/market-api/aggTrades.ts +++ b/src/tools/binance-spot/market-api/aggTrades.ts @@ -1,50 +1,52 @@ // src/tools/binance-spot/market-api/aggTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAggTrades(server: McpServer) { - server.tool( - "BinanceAggTrades", - "Get compressed, aggregate trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - fromId: z.number().optional().describe("ID to get aggregate trades from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.aggTrades(params); - - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved aggregate trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve aggregate trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceAggTrades", + { + description: "Get compressed, aggregate trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + fromId: z.number().optional().describe("ID to get aggregate trades from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.aggTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved aggregate trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve aggregate trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/avgPrice.ts b/src/tools/binance-spot/market-api/avgPrice.ts index 16107b77..4ccb304c 100644 --- a/src/tools/binance-spot/market-api/avgPrice.ts +++ b/src/tools/binance-spot/market-api/avgPrice.ts @@ -1,41 +1,43 @@ // src/tools/binance-spot/market-api/avgPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAvgPrice(server: McpServer) { - server.tool( - "BinanceAvgPrice", - "Get current average price for a trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const response = await spotClient.restAPI.avgPrice({ - symbol: symbol - }); + server.registerTool( + "BinanceAvgPrice", + { + description: "Get current average price for a trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const response = await (spotClient as any).restAPI.avgPrice({ + symbol: symbol, + }); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved current average price for ${symbol}. Average price: ${data.price}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved current average price for ${symbol}. Average price: ${data.price}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve average price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve average price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/depth.ts b/src/tools/binance-spot/market-api/depth.ts index b83f84d5..2ce263f5 100644 --- a/src/tools/binance-spot/market-api/depth.ts +++ b/src/tools/binance-spot/market-api/depth.ts @@ -1,43 +1,45 @@ // src/tools/binance-spot/market-api/depth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDepth(server: McpServer) { - server.tool( - "BinanceDepth", - "Get order book depth data for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Depth of the order book. Default 100; max 5000.") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.depth(params); + server.registerTool( + "BinanceDepth", + { + description: "Get order book depth data for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Depth of the order book. Default 100; max 5000."), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.depth(params); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved order book depth for ${symbol}. Bids: ${data.bids?.length || 0}, Asks: ${data.asks?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order book depth: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve order book depth: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/getTrades.ts b/src/tools/binance-spot/market-api/getTrades.ts index 7c885045..2ecffd7e 100644 --- a/src/tools/binance-spot/market-api/getTrades.ts +++ b/src/tools/binance-spot/market-api/getTrades.ts @@ -1,43 +1,46 @@ // src/tools/binance-spot/market-api/getTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetTrades(server: McpServer) { - server.tool( - "BinanceGetTrades", - "Get recent trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, limit }) => { - try { - const params: any = { symbol }; - - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.getTrades(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved recent trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve recent trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceGetTrades", + { + description: "Get recent trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, limit }) => { + try { + const params: any = { symbol }; + + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.getTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved recent trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve recent trades: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/historicalTrades.ts b/src/tools/binance-spot/market-api/historicalTrades.ts index cefd0378..4ac08777 100644 --- a/src/tools/binance-spot/market-api/historicalTrades.ts +++ b/src/tools/binance-spot/market-api/historicalTrades.ts @@ -1,45 +1,50 @@ // src/tools/binance-spot/market-api/historicalTrades.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceHistoricalTrades(server: McpServer) { - server.tool( - "BinanceHistoricalTrades", - "Get older historical trades for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - limit: z.number().optional().describe("Default 500; max 1000"), - fromId: z.number().optional().describe("Trade ID to fetch from") - }, - async ({ symbol, limit, fromId }) => { - try { - const params: any = { symbol }; - - if (limit !== undefined) params.limit = limit; - if (fromId !== undefined) params.fromId = fromId; - - const response = await spotClient.restAPI.historicalTrades(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved historical trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve historical trades: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceHistoricalTrades", + { + description: "Get older historical trades for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + limit: z.number().optional().describe("Default 500; max 1000"), + fromId: z.number().optional().describe("Trade ID to fetch from"), + }, + }, + async ({ symbol, limit, fromId }) => { + try { + const params: any = { symbol }; + + if (limit !== undefined) params.limit = limit; + if (fromId !== undefined) params.fromId = fromId; + + const response = await (spotClient as any).restAPI.historicalTrades(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved historical trades for ${symbol}. Total trades: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve historical trades: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/index.ts b/src/tools/binance-spot/market-api/index.ts index b0730073..51efb908 100644 --- a/src/tools/binance-spot/market-api/index.ts +++ b/src/tools/binance-spot/market-api/index.ts @@ -1,30 +1,30 @@ // src/tools/binance-spot/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceAggTrades } from "./aggTrades.js"; +import { registerBinanceAvgPrice } from "./avgPrice.js"; +import { registerBinanceDepth } from "./depth.js"; +import { registerBinanceGetTrades } from "./getTrades.js"; +import { registerBinanceHistoricalTrades } from "./historicalTrades.js"; import { registerBinanceKlines } from "./klines.js"; import { registerBinanceTicker24hr } from "./ticker24hr.js"; -import { registerBinanceDepth } from "./depth.js"; -import { registerBinanceAggTrades } from "./aggTrades.js"; -import { registerBinanceTickerTradingDay } from "./tickerTradingDay.js"; -import { registerBinanceUiKlines } from "./uiKlines.js"; +import { registerBinanceTicker } from "./ticker.js"; import { registerBinanceTickerBookTicker } from "./tickerBookTicker.js"; -import { registerBinanceAvgPrice } from "./avgPrice.js"; import { registerBinanceTickerPrice } from "./tickerPrice.js"; -import { registerBinanceTicker } from "./ticker.js"; -import { registerBinanceHistoricalTrades } from "./historicalTrades.js"; -import { registerBinanceGetTrades } from "./getTrades.js"; +import { registerBinanceTickerTradingDay } from "./tickerTradingDay.js"; +import { registerBinanceUiKlines } from "./uiKlines.js"; export function registerBinanceMarketApiTools(server: McpServer) { - registerBinanceKlines(server); - registerBinanceTicker24hr(server); - registerBinanceDepth(server); - registerBinanceAggTrades(server); - registerBinanceTickerTradingDay(server); - registerBinanceUiKlines(server); - registerBinanceTickerBookTicker(server); - registerBinanceAvgPrice(server); - registerBinanceTickerPrice(server); - registerBinanceTicker(server); - registerBinanceHistoricalTrades(server); - registerBinanceGetTrades(server); - -} \ No newline at end of file + registerBinanceKlines(server); + registerBinanceTicker24hr(server); + registerBinanceDepth(server); + registerBinanceAggTrades(server); + registerBinanceTickerTradingDay(server); + registerBinanceUiKlines(server); + registerBinanceTickerBookTicker(server); + registerBinanceAvgPrice(server); + registerBinanceTickerPrice(server); + registerBinanceTicker(server); + registerBinanceHistoricalTrades(server); + registerBinanceGetTrades(server); +} diff --git a/src/tools/binance-spot/market-api/klines.ts b/src/tools/binance-spot/market-api/klines.ts index 53e3fcf5..69ee69df 100644 --- a/src/tools/binance-spot/market-api/klines.ts +++ b/src/tools/binance-spot/market-api/klines.ts @@ -1,53 +1,72 @@ // src/tools/binance-spot/market-api/klines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceKlines(server: McpServer) { - server.tool( - "BinanceKlines", - "Get candlestick data (klines) for a specific trading pair and interval.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { - symbol, - interval - }; - - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.klines(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceKlines", + { + description: "Get candlestick data (klines) for a specific trading pair and interval.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { + symbol, + interval, + }; + + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.klines(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/ticker.ts b/src/tools/binance-spot/market-api/ticker.ts index 12e44187..085fb0a9 100644 --- a/src/tools/binance-spot/market-api/ticker.ts +++ b/src/tools/binance-spot/market-api/ticker.ts @@ -1,49 +1,57 @@ // src/tools/binance-spot/market-api/ticker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTicker(server: McpServer) { - server.tool( - "BinanceTicker", + server.registerTool( + "BinanceTicker", + { + description: "Get 24-hour rolling window price change statistics for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - windowSize: z.string().optional().describe("Defaults to 1d. Valid values: 1d, 2d, 3d, 4d, 5d, 6d, 7d") - }, - async ({ symbol, windowSize }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - if (windowSize) params.windowSize = windowSize; - - const response = await spotClient.restAPI.ticker(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved ticker statistics for all symbols${windowSize ? ` with window size ${windowSize}` : ''}. Total items: ${data.length}.` - : `Retrieved ticker statistics for ${symbol}${windowSize ? ` with window size ${windowSize}` : ''}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve ticker statistics: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + windowSize: z + .string() + .optional() + .describe("Defaults to 1d. Valid values: 1d, 2d, 3d, 4d, 5d, 6d, 7d"), + }, + }, + async ({ symbol, windowSize }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + if (windowSize) params.windowSize = windowSize; + + const response = await (spotClient as any).restAPI.ticker(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved ticker statistics for all symbols${windowSize ? ` with window size ${windowSize}` : ""}. Total items: ${data.length}.` + : `Retrieved ticker statistics for ${symbol}${windowSize ? ` with window size ${windowSize}` : ""}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve ticker statistics: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/ticker24hr.ts b/src/tools/binance-spot/market-api/ticker24hr.ts index 12ddce0d..35d607fb 100644 --- a/src/tools/binance-spot/market-api/ticker24hr.ts +++ b/src/tools/binance-spot/market-api/ticker24hr.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/ticker24hr.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTicker24hr(server: McpServer) { - server.tool( - "BinanceTicker24hr", - "Get 24-hour price change statistics for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.ticker24hr(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved 24hr statistics for all symbols. Total items: ${data.length}.` - : `Retrieved 24hr statistics for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve 24hr ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTicker24hr", + { + description: "Get 24-hour price change statistics for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.ticker24hr(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved 24hr statistics for all symbols. Total items: ${data.length}.` + : `Retrieved 24hr statistics for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve 24hr ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/tickerBookTicker.ts b/src/tools/binance-spot/market-api/tickerBookTicker.ts index 44a28791..103c86fb 100644 --- a/src/tools/binance-spot/market-api/tickerBookTicker.ts +++ b/src/tools/binance-spot/market-api/tickerBookTicker.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/tickerBookTicker.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerBookTicker(server: McpServer) { - server.tool( - "BinanceTickerBookTicker", - "Get best price/quantity on the order book for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerBookTicker(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved best price/quantity on the order book for all symbols. Total items: ${data.length}.` - : `Retrieved best price/quantity on the order book for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve book ticker: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerBookTicker", + { + description: "Get best price/quantity on the order book for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerBookTicker(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved best price/quantity on the order book for all symbols. Total items: ${data.length}.` + : `Retrieved best price/quantity on the order book for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve book ticker: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/tickerPrice.ts b/src/tools/binance-spot/market-api/tickerPrice.ts index 98313726..7a4ee56f 100644 --- a/src/tools/binance-spot/market-api/tickerPrice.ts +++ b/src/tools/binance-spot/market-api/tickerPrice.ts @@ -1,47 +1,49 @@ // src/tools/binance-spot/market-api/tickerPrice.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerPrice(server: McpServer) { - server.tool( - "BinanceTickerPrice", - "Get latest price for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerPrice(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved latest prices for all symbols. Total items: ${data.length}.` - : `Retrieved latest price for ${symbol}: ${data.price}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve ticker price: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerPrice", + { + description: "Get latest price for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerPrice(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved latest prices for all symbols. Total items: ${data.length}.` + : `Retrieved latest price for ${symbol}: ${data.price}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve ticker price: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/tickerTradingDay.ts b/src/tools/binance-spot/market-api/tickerTradingDay.ts index 7d96249e..0f43c545 100644 --- a/src/tools/binance-spot/market-api/tickerTradingDay.ts +++ b/src/tools/binance-spot/market-api/tickerTradingDay.ts @@ -1,47 +1,51 @@ // src/tools/binance-spot/market-api/tickerTradingDay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceTickerTradingDay(server: McpServer) { - server.tool( - "BinanceTickerTradingDay", - "Get statistics for the current trading day for a symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.tickerTradingDay(params); - - - const data = await response.data(); - - const isArray = Array.isArray(data); - const responseText = isArray - ? `Retrieved trading day statistics for all symbols. Total items: ${data.length}.` - : `Retrieved trading day statistics for ${symbol}.`; - - return { - content: [ - { - type: "text", - text: `${responseText} Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve trading day statistics: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceTickerTradingDay", + { + description: "Get statistics for the current trading day for a symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.tickerTradingDay(params); + + const data = await response.data(); + + const isArray = Array.isArray(data); + const responseText = isArray + ? `Retrieved trading day statistics for all symbols. Total items: ${data.length}.` + : `Retrieved trading day statistics for ${symbol}.`; + + return { + content: [ + { + type: "text", + text: `${responseText} Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve trading day statistics: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/market-api/uiKlines.ts b/src/tools/binance-spot/market-api/uiKlines.ts index 96100d2b..9a767f00 100644 --- a/src/tools/binance-spot/market-api/uiKlines.ts +++ b/src/tools/binance-spot/market-api/uiKlines.ts @@ -1,53 +1,72 @@ // src/tools/binance-spot/market-api/uiKlines.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceUiKlines(server: McpServer) { - server.tool( - "BinanceUiKlines", - "Get UI-optimized candlestick data for a specific trading pair and interval.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - interval: z.enum([ - "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M" - ]).describe("Kline interval"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500; max 1000") - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: any = { - symbol, - interval - }; - - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.uiKlines(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved UI klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve UI klines: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceUiKlines", + { + description: "Get UI-optimized candlestick data for a specific trading pair and interval.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + interval: z + .enum([ + "1m", + "3m", + "5m", + "15m", + "30m", + "1h", + "2h", + "4h", + "6h", + "8h", + "12h", + "1d", + "3d", + "1w", + "1M", + ]) + .describe("Kline interval"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500; max 1000"), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: any = { + symbol, + interval, + }; + + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.uiKlines(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved UI klines for ${symbol} with ${interval} interval. Total candles: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve UI klines: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/allOrders.ts b/src/tools/binance-spot/trade-api/allOrders.ts index d94ac840..41dcc20d 100644 --- a/src/tools/binance-spot/trade-api/allOrders.ts +++ b/src/tools/binance-spot/trade-api/allOrders.ts @@ -1,49 +1,55 @@ // src/tools/binance-spot/trade-api/allOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceAllOrders(server: McpServer) { - server.tool( - "BinanceAllOrders", - "Get all account orders for a specific symbol; active, canceled, or filled.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.number().optional().describe("Order ID to start from"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Maximum number of orders to return (default 500, max 1000)") - }, - async ({ symbol, orderId, startTime, endTime, limit }) => { - try { - const params: any = { symbol }; - - if (orderId !== undefined) params.orderId = orderId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const response = await spotClient.restAPI.allOrders(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Retrieved all orders for ${symbol}. Total orders: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve all orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceAllOrders", + { + description: "Get all account orders for a specific symbol; active, canceled, or filled.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.number().optional().describe("Order ID to start from"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z + .number() + .optional() + .describe("Maximum number of orders to return (default 500, max 1000)"), + }, + }, + async ({ symbol, orderId, startTime, endTime, limit }) => { + try { + const params: any = { symbol }; + + if (orderId !== undefined) params.orderId = orderId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const response = await (spotClient as any).restAPI.allOrders(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved all orders for ${symbol}. Total orders: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to retrieve all orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/deleteOpenOrders.ts b/src/tools/binance-spot/trade-api/deleteOpenOrders.ts index 1cdaca3f..541b9de6 100644 --- a/src/tools/binance-spot/trade-api/deleteOpenOrders.ts +++ b/src/tools/binance-spot/trade-api/deleteOpenOrders.ts @@ -1,40 +1,43 @@ // src/tools/binance-spot/trade-api/deleteOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteOpenOrders(server: McpServer) { - server.tool( - "BinanceDeleteOpenOrders", - "Cancel all open orders on Binance for a specific symbol.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const response = await spotClient.restAPI.deleteOpenOrders({ - symbol: symbol - }); + server.registerTool( + "BinanceDeleteOpenOrders", + { + description: "Cancel all open orders on Binance for a specific symbol.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const response = await (spotClient as any).restAPI.deleteOpenOrders({ + symbol: symbol, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully canceled all open orders for ${symbol}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully canceled all open orders for ${symbol}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to cancel open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/deleteOrder.ts b/src/tools/binance-spot/trade-api/deleteOrder.ts index 027bdde0..ac8036f0 100644 --- a/src/tools/binance-spot/trade-api/deleteOrder.ts +++ b/src/tools/binance-spot/trade-api/deleteOrder.ts @@ -1,45 +1,48 @@ // src/tools/binance-spot/trade-api/deleteOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteOrder(server: McpServer) { - server.tool( - "BinanceDeleteOrder", - "Cancel an active order on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.string().optional().describe("The order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - - if (orderId) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; - - const response = await spotClient.restAPI.deleteOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Order successfully canceled. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to cancel order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceDeleteOrder", + { + description: "Cancel an active order on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.string().optional().describe("The order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + + if (orderId) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const response = await (spotClient as any).restAPI.deleteOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Order successfully canceled. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/getOpenOrders.ts b/src/tools/binance-spot/trade-api/getOpenOrders.ts index 0f129727..9d36a0ad 100644 --- a/src/tools/binance-spot/trade-api/getOpenOrders.ts +++ b/src/tools/binance-spot/trade-api/getOpenOrders.ts @@ -1,41 +1,44 @@ // src/tools/binance-spot/trade-api/getOpenOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetOpenOrders(server: McpServer) { - server.tool( - "BinanceGetOpenOrders", - "Get all open orders on Binance for a specific symbol or all symbols.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.getOpenOrders(params); + server.registerTool( + "BinanceGetOpenOrders", + { + description: "Get all open orders on Binance for a specific symbol or all symbols.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.getOpenOrders(params); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved open orders${symbol ? ` for ${symbol}` : ""}. Total open orders: ${data.length}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open orders${symbol ? ` for ${symbol}` : ''}. Total open orders: ${data.length}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/getOrder.ts b/src/tools/binance-spot/trade-api/getOrder.ts index e7647207..3357bf2b 100644 --- a/src/tools/binance-spot/trade-api/getOrder.ts +++ b/src/tools/binance-spot/trade-api/getOrder.ts @@ -1,45 +1,50 @@ // src/tools/binance-spot/trade-api/getOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceGetOrder(server: McpServer) { - server.tool( - "BinanceGetOrder", - "Check an order's status on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - orderId: z.string().optional().describe("The order ID to query"), - origClientOrderId: z.string().optional().describe("Original client order ID") - }, - async ({ symbol, orderId, origClientOrderId }) => { - try { - const params: any = { symbol }; - - if (orderId) params.orderId = orderId; - if (origClientOrderId) params.origClientOrderId = origClientOrderId; - - const response = await spotClient.restAPI.getOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `Order information retrieved successfully. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve order information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceGetOrder", + { + description: "Check an order's status on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + orderId: z.string().optional().describe("The order ID to query"), + origClientOrderId: z.string().optional().describe("Original client order ID"), + }, + }, + async ({ symbol, orderId, origClientOrderId }) => { + try { + const params: any = { symbol }; + + if (orderId) params.orderId = orderId; + if (origClientOrderId) params.origClientOrderId = origClientOrderId; + + const response = await (spotClient as any).restAPI.getOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Order information retrieved successfully. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to retrieve order information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/index.ts b/src/tools/binance-spot/trade-api/index.ts index 1478bdd3..dac0fe57 100644 --- a/src/tools/binance-spot/trade-api/index.ts +++ b/src/tools/binance-spot/trade-api/index.ts @@ -1,22 +1,22 @@ // src/tools/binance-spot/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceDeleteOrder } from "./deleteOrder.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceAllOrders } from "./allOrders.js"; -import { registerBinanceOpenOrderList } from "./openOrderList.js"; -import { registerBinanceNewOrder } from "./newOrder.js"; -import { registerBinanceGetOrder } from "./getOrder.js"; -import { registerBinanceGetOpenOrders } from "./getOpenOrders.js"; import { registerBinanceDeleteOpenOrders } from "./deleteOpenOrders.js"; +import { registerBinanceDeleteOrder } from "./deleteOrder.js"; +import { registerBinanceGetOpenOrders } from "./getOpenOrders.js"; +import { registerBinanceGetOrder } from "./getOrder.js"; +import { registerBinanceNewOrder } from "./newOrder.js"; +import { registerBinanceOpenOrderList } from "./openOrderList.js"; import { registerBinanceOrderOco } from "./orderOco.js"; export function registerBinanceTradeApiTools(server: McpServer) { - registerBinanceDeleteOrder(server); - registerBinanceAllOrders(server); - registerBinanceOpenOrderList(server); - registerBinanceNewOrder(server); - registerBinanceGetOrder(server); - registerBinanceGetOpenOrders(server); - registerBinanceDeleteOpenOrders(server); - registerBinanceOrderOco(server); - -} \ No newline at end of file + registerBinanceDeleteOrder(server); + registerBinanceAllOrders(server); + registerBinanceOpenOrderList(server); + registerBinanceNewOrder(server); + registerBinanceGetOrder(server); + registerBinanceGetOpenOrders(server); + registerBinanceDeleteOpenOrders(server); + registerBinanceOrderOco(server); +} diff --git a/src/tools/binance-spot/trade-api/newOrder.ts b/src/tools/binance-spot/trade-api/newOrder.ts index 1b01cfe5..e62eb377 100644 --- a/src/tools/binance-spot/trade-api/newOrder.ts +++ b/src/tools/binance-spot/trade-api/newOrder.ts @@ -1,63 +1,102 @@ // src/tools/binance-spot/trade-api/newOrder.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; +/** Binance allows only [a-zA-Z0-9-_], max 36 chars. */ +function sanitizeNewClientOrderId(value: string): string { + return value.replace(/[^a-zA-Z0-9-_]/g, "").slice(0, 36); +} + export function registerBinanceNewOrder(server: McpServer) { - server.tool( - "BinanceNewOrder", - "Create a new order on Binance for a specific trading pair.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), - type: z.enum(["LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]).describe("Order type"), - timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), - quantity: z.number().describe("Order quantity"), - quoteOrderQty: z.number().optional().describe("Quote order quantity"), - price: z.number().optional().describe("Order price"), - newClientOrderId: z.string().optional().describe("Client order ID"), - stopPrice: z.number().optional().describe("Stop price"), - icebergQty: z.number().optional().describe("Iceberg quantity"), - newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type") - }, - async ({ symbol, side, type, timeInForce, quantity, quoteOrderQty, price, newClientOrderId, stopPrice, icebergQty, newOrderRespType }) => { - try { - const params: any = { - symbol, - side, - type, - quantity - }; - - if (timeInForce) params.timeInForce = timeInForce; - if (quoteOrderQty !== undefined) params.quoteOrderQty = quoteOrderQty; - if (price !== undefined) params.price = price; - if (newClientOrderId) params.newClientOrderId = newClientOrderId; - if (stopPrice !== undefined) params.stopPrice = stopPrice; - if (icebergQty !== undefined) params.icebergQty = icebergQty; - if (newOrderRespType) params.newOrderRespType = newOrderRespType; - - const response = await spotClient.restAPI.newOrder(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `New order successfully created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create new order: ${errorMessage}` } - ], - isError: true - }; - } + server.registerTool( + "BinanceNewOrder", + { + description: "Create a new order on Binance for a specific trading pair.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), + type: z + .enum([ + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", + ]) + .describe("Order type"), + timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force"), + quantity: z.number().describe("Order quantity"), + quoteOrderQty: z.number().optional().describe("Quote order quantity"), + price: z.number().optional().describe("Order price"), + newClientOrderId: z + .string() + .optional() + .describe("Client order ID: only a-zA-Z0-9-_ allowed, max 36 chars"), + stopPrice: z.number().optional().describe("Stop price"), + icebergQty: z.number().optional().describe("Iceberg quantity"), + newOrderRespType: z.enum(["ACK", "RESULT", "FULL"]).optional().describe("Response type"), + }, + }, + async ({ + symbol, + side, + type, + timeInForce, + quantity, + quoteOrderQty, + price, + newClientOrderId, + stopPrice, + icebergQty, + newOrderRespType, + }) => { + try { + const params: any = { + symbol, + side, + type, + quantity, + }; + + const timeInForceTypes = ["LIMIT", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]; + if (timeInForce && timeInForceTypes.includes(type)) params.timeInForce = timeInForce; + if (type === "MARKET" && quoteOrderQty !== undefined) params.quoteOrderQty = quoteOrderQty; + const priceTypes = ["LIMIT", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT", "LIMIT_MAKER"]; + if (price !== undefined && priceTypes.includes(type)) params.price = price; + if (newClientOrderId) { + const sanitized = sanitizeNewClientOrderId(newClientOrderId); + if (sanitized) params.newClientOrderId = sanitized; } - ); -} \ No newline at end of file + const stopOrderTypes = ["STOP_LOSS", "STOP_LOSS_LIMIT", "TAKE_PROFIT", "TAKE_PROFIT_LIMIT"]; + if (stopPrice !== undefined && stopOrderTypes.includes(type)) params.stopPrice = stopPrice; + if (icebergQty !== undefined) params.icebergQty = icebergQty; + if (newOrderRespType) params.newOrderRespType = newOrderRespType; + + const response = await (spotClient as any).restAPI.newOrder(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `New order successfully created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create new order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/openOrderList.ts b/src/tools/binance-spot/trade-api/openOrderList.ts index 7c6134f5..02ae7c12 100644 --- a/src/tools/binance-spot/trade-api/openOrderList.ts +++ b/src/tools/binance-spot/trade-api/openOrderList.ts @@ -1,41 +1,44 @@ // src/tools/binance-spot/trade-api/openOrderList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceOpenOrderList(server: McpServer) { - server.tool( - "BinanceOpenOrderList", - "Query open OCO orders for a specific account or symbol.", - { - symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)") - }, - async ({ symbol }) => { - try { - const params: any = {}; - if (symbol) params.symbol = symbol; - - const response = await spotClient.restAPI.openOrderList(params); + server.registerTool( + "BinanceOpenOrderList", + { + description: "Query open OCO orders for a specific account or symbol.", + inputSchema: { + symbol: z.string().optional().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + }, + }, + async ({ symbol }) => { + try { + const params: any = {}; + if (symbol) params.symbol = symbol; + + const response = await (spotClient as any).restAPI.openOrderList(params); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved open OCO orders${symbol ? ` for ${symbol}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open OCO orders${symbol ? ` for ${symbol}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open OCO orders: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open OCO orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/trade-api/orderOco.ts b/src/tools/binance-spot/trade-api/orderOco.ts index b758bf40..b3e09c8e 100644 --- a/src/tools/binance-spot/trade-api/orderOco.ts +++ b/src/tools/binance-spot/trade-api/orderOco.ts @@ -1,63 +1,81 @@ // src/tools/binance-spot/trade-api/orderOco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceOrderOco(server: McpServer) { - server.tool( - "BinanceOrderOco", - "Send a new OCO (One-Cancels-the-Other) order on Binance.", - { - symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), - side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), - quantity: z.number().describe("Order quantity"), - price: z.number().describe("Order price"), - stopPrice: z.number().describe("Stop price"), - stopLimitPrice: z.number().optional().describe("Stop limit price"), - stopLimitTimeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Stop limit time in force"), - newClientOrderId: z.string().optional().describe("Client order ID for the limit order"), - stopClientOrderId: z.string().optional().describe("Client order ID for the stop order"), - limitIcebergQty: z.number().optional().describe("Limit iceberg quantity"), - stopIcebergQty: z.number().optional().describe("Stop iceberg quantity") - }, - async ({ symbol, side, quantity, price, stopPrice, stopLimitPrice, stopLimitTimeInForce, newClientOrderId, stopClientOrderId, limitIcebergQty, stopIcebergQty }) => { - try { - const params: any = { - symbol, - side, - quantity, - price, - stopPrice - }; - - if (stopLimitPrice !== undefined) params.stopLimitPrice = stopLimitPrice; - if (stopLimitTimeInForce) params.stopLimitTimeInForce = stopLimitTimeInForce; - if (newClientOrderId) params.newClientOrderId = newClientOrderId; - if (stopClientOrderId) params.stopClientOrderId = stopClientOrderId; - if (limitIcebergQty !== undefined) params.limitIcebergQty = limitIcebergQty; - if (stopIcebergQty !== undefined) params.stopIcebergQty = stopIcebergQty; - - const response = await spotClient.restAPI.orderOco(params); - - const data = await response.data(); - - return { - content: [ - { - type: "text", - text: `OCO order successfully created. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create OCO order: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + server.registerTool( + "BinanceOrderOco", + { + description: "Send a new OCO (One-Cancels-the-Other) order on Binance.", + inputSchema: { + symbol: z.string().describe("Symbol of the trading pair (e.g., BTCUSDT)"), + side: z.enum(["BUY", "SELL"]).describe("Order side: BUY or SELL"), + quantity: z.number().describe("Order quantity"), + price: z.number().describe("Order price"), + stopPrice: z.number().describe("Stop price"), + stopLimitPrice: z.number().optional().describe("Stop limit price"), + stopLimitTimeInForce: z + .enum(["GTC", "IOC", "FOK"]) + .optional() + .describe("Stop limit time in force"), + newClientOrderId: z.string().optional().describe("Client order ID for the limit order"), + stopClientOrderId: z.string().optional().describe("Client order ID for the stop order"), + limitIcebergQty: z.number().optional().describe("Limit iceberg quantity"), + stopIcebergQty: z.number().optional().describe("Stop iceberg quantity"), + }, + }, + async ({ + symbol, + side, + quantity, + price, + stopPrice, + stopLimitPrice, + stopLimitTimeInForce, + newClientOrderId, + stopClientOrderId, + limitIcebergQty, + stopIcebergQty, + }) => { + try { + const params: any = { + symbol, + side, + quantity, + price, + stopPrice, + }; + + if (stopLimitPrice !== undefined) params.stopLimitPrice = stopLimitPrice; + if (stopLimitTimeInForce) params.stopLimitTimeInForce = stopLimitTimeInForce; + if (newClientOrderId) params.newClientOrderId = newClientOrderId; + if (stopClientOrderId) params.stopClientOrderId = stopClientOrderId; + if (limitIcebergQty !== undefined) params.limitIcebergQty = limitIcebergQty; + if (stopIcebergQty !== undefined) params.stopIcebergQty = stopIcebergQty; + + const response = await (spotClient as any).restAPI.orderOco(params); + + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `OCO order successfully created. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts b/src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts index 7f6001f4..5dfa7052 100644 --- a/src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts +++ b/src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts @@ -1,40 +1,43 @@ // src/tools/binance-spot/userdatastream-api/deleteUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceDeleteUserDataStream(server: McpServer) { - server.tool( - "BinanceDeleteUserDataStream", - "Close a user data stream by invalidating the listen key.", - { - listenKey: z.string().describe("Listen key to close") - }, - async ({ listenKey }) => { - try { - const response = await spotClient.restAPI.deleteUserDataStream({ - listenKey: listenKey - }); + server.registerTool( + "BinanceDeleteUserDataStream", + { + description: "Close a user data stream by invalidating the listen key.", + inputSchema: { + listenKey: z.string().describe("Listen key to close"), + }, + }, + async ({ listenKey }) => { + try { + const response = await (spotClient as any).restAPI.deleteUserDataStream({ + listenKey: listenKey, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully closed user data stream with listen key: ${listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully closed user data stream with listen key: ${listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to close user data stream: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to close user data stream: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/userdatastream-api/index.ts b/src/tools/binance-spot/userdatastream-api/index.ts index f6e3f61c..288eaa88 100644 --- a/src/tools/binance-spot/userdatastream-api/index.ts +++ b/src/tools/binance-spot/userdatastream-api/index.ts @@ -1,12 +1,12 @@ // src/tools/binance-spot/userdatastream-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceNewUserDataStream } from "./newUserDataStream.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceDeleteUserDataStream } from "./deleteUserDataStream.js"; +import { registerBinanceNewUserDataStream } from "./newUserDataStream.js"; import { registerBinancePutUserDataStream } from "./putUserDataStream.js"; export function registerBinanceUserDataStreamApiTools(server: McpServer) { - registerBinanceNewUserDataStream(server); - registerBinanceDeleteUserDataStream(server); - registerBinancePutUserDataStream(server); - + registerBinanceNewUserDataStream(server); + registerBinanceDeleteUserDataStream(server); + registerBinancePutUserDataStream(server); } diff --git a/src/tools/binance-spot/userdatastream-api/newUserDataStream.ts b/src/tools/binance-spot/userdatastream-api/newUserDataStream.ts index 767167dd..74dd45f0 100644 --- a/src/tools/binance-spot/userdatastream-api/newUserDataStream.ts +++ b/src/tools/binance-spot/userdatastream-api/newUserDataStream.ts @@ -1,36 +1,34 @@ // src/tools/binance-spot/userdatastream-api/newUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinanceNewUserDataStream(server: McpServer) { - server.tool( - "BinanceNewUserDataStream", - "Create a new user data stream to receive account updates via WebSocket.", - {}, - async () => { - try { - const response = await spotClient.restAPI.newUserDataStream(); + server.registerTool( + "BinanceNewUserDataStream", + { description: "Create a new user data stream to receive account updates via WebSocket." }, + async () => { + try { + const response = await (spotClient as any).restAPI.newUserDataStream(); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Created new listen key for user data stream. Listen key: ${data.listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Created new listen key for user data stream. Listen key: ${data.listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create user data stream: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to create user data stream: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-spot/userdatastream-api/putUserDataStream.ts b/src/tools/binance-spot/userdatastream-api/putUserDataStream.ts index 4e05e565..63568ebe 100644 --- a/src/tools/binance-spot/userdatastream-api/putUserDataStream.ts +++ b/src/tools/binance-spot/userdatastream-api/putUserDataStream.ts @@ -1,40 +1,45 @@ // src/tools/binance-spot/userdatastream-api/putUserDataStream.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { spotClient } from "../../../config/binanceClient.js"; export function registerBinancePutUserDataStream(server: McpServer) { - server.tool( - "BinancePutUserDataStream", - "Extend the validity of a user data stream listen key.", - { - listenKey: z.string().describe("Listen key to keep alive") - }, - async ({ listenKey }) => { - try { - const response = await spotClient.restAPI.putUserDataStream({ - listenKey: listenKey - }); + server.registerTool( + "BinancePutUserDataStream", + { + description: "Extend the validity of a user data stream listen key.", + inputSchema: { + listenKey: z.string().describe("Listen key to keep alive"), + }, + }, + async ({ listenKey }) => { + try { + const response = await (spotClient as any).restAPI.putUserDataStream({ + listenKey: listenKey, + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully extended validity of listen key: ${listenKey}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully extended validity of listen key: ${listenKey}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to extend listen key validity: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to extend listen key validity: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts b/src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts index aeff9941..cad0c72b 100644 --- a/src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts +++ b/src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/ethStakingAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceEthStakingAccount(server: McpServer) { - server.tool( - "BinanceEthStakingAccount", + server.registerTool( + "BinanceEthStakingAccount", + { + description: "ETH Staking Account API allows users to retrieve their current ETH staking holdings and 30-day profit details, including amounts from WBETH and BETH", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.ethStakingAccount({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.ethStakingAccount({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current ETH staking holdings . Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current ETH staking holdings . Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve ETH staking holdings . ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve ETH staking holdings . ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts b/src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts index ed542bda..7275a607 100644 --- a/src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts +++ b/src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/getCurrentEthStakingQuota.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetCurrentEthStakingQuota(server: McpServer) { - server.tool( - "BinanceGetCurrentEthStakingQuota", + server.registerTool( + "BinanceGetCurrentEthStakingQuota", + { + description: "Get Current ETH Staking Quota API allows users to retrieve their available ETH staking and redemption quotas, reflecting personal and daily limits.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current ETH Staking Quota API allows users. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current ETH Staking Quota API allows users. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve current ETH Staking Quota API allows users. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve current ETH Staking Quota API allows users. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts b/src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts index 4f86c09c..98eeae75 100644 --- a/src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getEthRedemptionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetEthRedemptionHistory(server: McpServer) { - server.tool( - "BinanceGetEthRedemptionHistory", + server.registerTool( + "BinanceGetEthRedemptionHistory", + { + description: "Get ETH Redemption History API allows users to retrieve their historical ETH staking redemption records, including details like asset type, amount, status, and time of redemption.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page, start from 1. Default is 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page, Default is 10, Max is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page, start from 1. Default is 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page, Default is 10, Max is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getCurrentEthStakingQuota({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved history API allows users to retrieve their historical ETH staking redemption records. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved history API allows users to retrieve their historical ETH staking redemption records. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve history API allows users to retrieve their historical ETH staking redemption records. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve history API allows users to retrieve their historical ETH staking redemption records. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts b/src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts index e93d94d9..e41ef5ac 100644 --- a/src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getEthStakingHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetEthStakingHistory(server: McpServer) { - server.tool( - "registerBinanceGetEthStakingHistory", + server.registerTool( + "registerBinanceGetEthStakingHistory", + { + description: "Get ETH Staking History API allows users to retrieve their historical ETH staking records, including details like asset type, amount, status, and time of staking", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522526562)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default is 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default is 10, Max is 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getEthStakingHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522526562)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default is 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default is 10, Max is 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getEthStakingHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved ETH Staking History API allows users to retrieve their historical ETH staking records. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved ETH Staking History API allows users to retrieve their historical ETH staking records. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve ETH Staking History API allows users to retrieve their historical ETH staking records. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve ETH Staking History API allows users to retrieve their historical ETH staking records. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts b/src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts index d54febd0..e2c1056e 100644 --- a/src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts @@ -1,67 +1,77 @@ // src/tools/binance-staking/ETH-staking-api/getWbethRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethRateHistory(server: McpServer) { - server.tool( - "BinanceGetWbethRateHistory", + server.registerTool( + "BinanceGetWbethRateHistory", + { + description: "Get WBETH Rate History API allows users to retrieve historical WBETH exchange rates and BETH annual percentage rates (APR) within a specified time range.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Starts from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Starts from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + + recvWindow: z + .number() + .int() + .optional() + .describe("Time window for request validity (in milliseconds)"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethRateHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); - recvWindow: z.number().int().optional().describe("Time window for request validity (in milliseconds)") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethRateHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical WBETH exchange rates and BETH annual percentage rates. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical WBETH exchange rates and BETH annual percentage rates. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical WBETH exchange rates and BETH annual percentage rates. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical WBETH exchange rates and BETH annual percentage rates. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts b/src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts index e0c06400..a02a08ff 100644 --- a/src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts @@ -1,66 +1,80 @@ // src/tools/binance-staking/ETH-staking-api/getWbethRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetWbethRewardsHistory", + server.registerTool( + "BinanceGetWbethRewardsHistory", + { + description: "Get WBETH Rewards History API allows users to retrieve historical reward data earned from WBETH holdings, including estimated rewards in ETH, holding amounts, and APR details.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (e.g., 1641522717552)"), - endTime: z.number().int().optional().describe("End time in milliseconds (e.g., 1641522720000)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethRewardsHistory({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }) - }); + inputSchema: { + startTime: z + .number() + .int() + .optional() + .describe("Start time in milliseconds (e.g., 1641522717552)"), + endTime: z + .number() + .int() + .optional() + .describe("End time in milliseconds (e.g., 1641522720000)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethRewardsHistory({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical reward data earned from WBETH holdings. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical reward data earned from WBETH holdings. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical reward data earned from WBETH holdings. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical reward data earned from WBETH holdings. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts b/src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts index 9167ac06..12fcdb90 100644 --- a/src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts @@ -1,66 +1,76 @@ // src/tools/binance-staking/ETH-staking-api/getWbethUnwrapHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethUnwrapHistory(server: McpServer) { - server.tool( - "BinanceGetWbethUnwrapHistory", + server.registerTool( + "BinanceGetWbethUnwrapHistory", + { + description: "Get WBETH Unwrap History API allows users to retrieve historical records of WBETH unwrap operations, including asset conversion details, exchange rates, and transaction status.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity (in milliseconds)") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethUnwrapHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Time window for request validity (in milliseconds)"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethUnwrapHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical records of WBETH unwrap operations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical records of WBETH unwrap operations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical records of WBETH unwrap operations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical records of WBETH unwrap operations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts b/src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts index e6295b81..5b69ef1d 100644 --- a/src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts +++ b/src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts @@ -1,66 +1,72 @@ // src/tools/binance-staking/ETH-staking-api/getWbethWrapHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetWbethWrapHistory(server: McpServer) { - server.tool( - "BinanceGetWbethWrapHistory", + server.registerTool( + "BinanceGetWbethWrapHistory", + { + description: "Get WBETH Wrap History API allows users to retrieve historical records of WBETH wrap operations, including asset conversion details, exchange rates, and transaction status.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getWbethWrapHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getWbethWrapHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical records of WBETH wrap operations. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical records of WBETH wrap operations. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical records of WBETH wrap operations. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical records of WBETH wrap operations. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/index.ts b/src/tools/binance-staking/ETH-staking-api/index.ts index f2641ade..9430f1f2 100644 --- a/src/tools/binance-staking/ETH-staking-api/index.ts +++ b/src/tools/binance-staking/ETH-staking-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-staking/ETH-staking-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceEthStakingAccount } from "./ethStakingAccount.js"; import { registerBinanceGetCurrentEthStakingQuota } from "./getCurrentEthStakingQuota.js"; import { registerBinanceGetEthRedemptionHistory } from "./getEthRedemptionHistory.js"; @@ -13,15 +14,15 @@ import { registerBinanceSubscribeEthStaking } from "./subscribeEthStaking.js"; import { registerBinanceWrapBeth } from "./wrapBeth.js"; export function registerBinanceETHStakingApiTools(server: McpServer) { - registerBinanceEthStakingAccount(server); - registerBinanceGetCurrentEthStakingQuota(server); - registerBinanceGetEthRedemptionHistory(server); - registerBinanceGetEthStakingHistory(server); - registerBinanceGetWbethRateHistory(server); - registerBinanceGetWbethRewardsHistory(server); - registerBinanceGetWbethUnwrapHistory(server); - registerBinanceGetWbethWrapHistory(server); - registerBinanceRedeemEth(server); - registerBinanceSubscribeEthStaking(server); - registerBinanceWrapBeth(server); + registerBinanceEthStakingAccount(server); + registerBinanceGetCurrentEthStakingQuota(server); + registerBinanceGetEthRedemptionHistory(server); + registerBinanceGetEthStakingHistory(server); + registerBinanceGetWbethRateHistory(server); + registerBinanceGetWbethRewardsHistory(server); + registerBinanceGetWbethUnwrapHistory(server); + registerBinanceGetWbethWrapHistory(server); + registerBinanceRedeemEth(server); + registerBinanceSubscribeEthStaking(server); + registerBinanceWrapBeth(server); } diff --git a/src/tools/binance-staking/ETH-staking-api/redeemEth.ts b/src/tools/binance-staking/ETH-staking-api/redeemEth.ts index 20dc7b60..ba81b6fb 100644 --- a/src/tools/binance-staking/ETH-staking-api/redeemEth.ts +++ b/src/tools/binance-staking/ETH-staking-api/redeemEth.ts @@ -1,47 +1,57 @@ // src/tools/binance-staking/ETH-staking-api/redeemEth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemEth(server: McpServer) { - server.tool( - "BinanceRedeemEth", + server.registerTool( + "BinanceRedeemEth", + { + description: "Redeem ETH API allows users to redeem WBETH or BETH for ETH, providing the amount, conversion ratio, and arrival time details.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 8 decimals (mandatory)"), - asset: z.string().optional().default("BETH").describe("Asset type, either WBETH or BETH. Default: BETH"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.redeemEth({ - amount: params.amount, - asset: params.asset, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 8 decimals (mandatory)"), + asset: z + .string() + .optional() + .default("BETH") + .describe("Asset type, either WBETH or BETH. Default: BETH"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.redeemEth({ + amount: params.amount, + asset: params.asset, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully redeemed WBETH or BETH for ETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully redeemed WBETH or BETH for ETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to redeem WBETH or BETH for ETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to redeem WBETH or BETH for ETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts b/src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts index b10e1946..ef4108b9 100644 --- a/src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts +++ b/src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETH-staking-api/subscribeEthStaking.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeEthStaking(server: McpServer) { - server.tool( - "BinanceSubscribeEthStaking", + server.registerTool( + "BinanceSubscribeEthStaking", + { + description: "Subscribe ETH Staking API allows users to stake ETH and receive WBETH, providing the staked amount and the conversion ratio for ETH to WBETH.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.subscribeEthStaking({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.subscribeEthStaking({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully staked ETH and receive WBETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully staked ETH and receive WBETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to stake ETH and receive WBETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to stake ETH and receive WBETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/ETH-staking-api/wrapBeth.ts b/src/tools/binance-staking/ETH-staking-api/wrapBeth.ts index c753711a..2d64825f 100644 --- a/src/tools/binance-staking/ETH-staking-api/wrapBeth.ts +++ b/src/tools/binance-staking/ETH-staking-api/wrapBeth.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/ETHStaking-api/wrapBeth.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceWrapBeth(server: McpServer) { - server.tool( - "BinanceWrapBeth", + server.registerTool( + "BinanceWrapBeth", + { + description: "Wrap BETH API allows users to convert BETH into WBETH, providing the wrapped WBETH amount and the exchange rate from BETH to WBETH.", - { - amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.wrapBeth({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in BETH, limit 4 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.wrapBeth({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully convert BETH into WBETH. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully convert BETH into WBETH. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to convert BETH into WBETH. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to convert BETH into WBETH. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts b/src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts index fbb1eaaf..dfb6a7f6 100644 --- a/src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts +++ b/src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/claimBoostRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceClaimBoostRewards(server: McpServer) { - server.tool( - "BinanceClaimBoostRewards", + server.registerTool( + "BinanceClaimBoostRewards", + { + description: "Claim Boost Rewards API allows users to claim their Boost APR airdrop rewards for staking.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.claimBoostRewards({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.claimBoostRewards({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully claim Boost APR airdrop rewards for staking. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully claim Boost APR airdrop rewards for staking. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to claim Boost APR airdrop rewards. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to claim Boost APR airdrop rewards. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts b/src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts index 8d3c5a97..613f8029 100644 --- a/src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts +++ b/src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts @@ -1,66 +1,72 @@ // src/tools/binance-staking/SOL-staking-api/getBnsolRateHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBnsolRateHistory(server: McpServer) { - server.tool( - "registerBinanceGetBnsolRateHistory", + server.registerTool( + "registerBinanceGetBnsolRateHistory", + { + description: " Get BNSOL Rate History API allows users to retrieve the historical data of the BNSOL staking rate, including APR and exchange rates for SOL to BNSOL.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBnsolRateHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBnsolRateHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the historical data of the BNSOL staking rate. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the historical data of the BNSOL staking rate. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the historical data of the BNSOL staking rate. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the historical data of the BNSOL staking rate. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts b/src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts index 360311b2..a74c3c10 100644 --- a/src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts +++ b/src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts @@ -1,71 +1,77 @@ // src/tools/binance-staking/SOL-staking-api/getBnsolRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBnsolRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetBnsolRewardsHistory", + server.registerTool( + "BinanceGetBnsolRewardsHistory", + { + description: "Get Boost Rewards History API allows users to retrieve their historical boost rewards data for staking, including the amount of rewards, token type (e.g., SOL), and status of the rewards (e.g., CLAIM, DISTRIBUTE).", - { - type: z - .enum(["CLAIM", "DISTRIBUTE"]) - .default("CLAIM") - .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBnsolRewardsHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), - ...(params.type && { type: params.type }) - }); + inputSchema: { + type: z + .enum(["CLAIM", "DISTRIBUTE"]) + .default("CLAIM") + .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBnsolRewardsHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + ...(params.type && { type: params.type }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved historical boost rewards data for staking. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved historical boost rewards data for staking. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve historical boost rewards data for staking. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve historical boost rewards data for staking. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts b/src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts index 790b2f0e..f0d856f9 100644 --- a/src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts +++ b/src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts @@ -1,70 +1,76 @@ // src/tools/binance-staking/SOL-staking-api/getBoostRewardsHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBoostRewardsHistory(server: McpServer) { - server.tool( - "BinanceGetBoostRewardsHistory", + server.registerTool( + "BinanceGetBoostRewardsHistory", + { + description: "Get Boost Rewards History API allows users to retrieve their boost rewards history for staking activities. This includes the amount of rewards received, the token type (e.g., SOL), and the status of the rewards (e.g., CLAIM or DISTRIBUTE).", - { - type: z - .enum(["CLAIM", "DISTRIBUTE"]) - .default("CLAIM") - .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getBoostRewardsHistory({ - type: params.type, - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + type: z + .enum(["CLAIM", "DISTRIBUTE"]) + .default("CLAIM") + .describe('Type of action. Must be "CLAIM" or "DISTRIBUTE". Default: "CLAIM"'), + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getBoostRewardsHistory({ + type: params.type, + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved boost rewards history for staking activities. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved boost rewards history for staking activities. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve boost rewards history for staking activities. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve boost rewards history for staking activities. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts b/src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts index 009a340c..678447ab 100644 --- a/src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts +++ b/src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts @@ -1,64 +1,70 @@ // src/tools/binance-staking/SOL-staking-api/getSolRedemptionHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolRedemptionHistory(server: McpServer) { - server.tool( - "BinanceGetSolRedemptionHistory", + server.registerTool( + "BinanceGetSolRedemptionHistory", + { + description: "Get SOL Redemption History API allows users to retrieve their SOL redemption history, detailing the amount of BNSOL redeemed for SOL and the exchange rate.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolRedemptionHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolRedemptionHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved SOL redemption history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved SOL redemption history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL redemption history. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL redemption history. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts b/src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts index cb8f4ec9..5e059682 100644 --- a/src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts +++ b/src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts @@ -1,64 +1,70 @@ // src/tools/binance-staking/SOL-staking-api/getSolStakingHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolStakingHistory(server: McpServer) { - server.tool( - "BinanceGetSolStakingHistory", + server.registerTool( + "BinanceGetSolStakingHistory", + { + description: "Get SOL Staking History API allows users to retrieve their SOL staking history, including details about the amount of SOL staked, the equivalent BNSOL amount distributed, the exchange rate, and the status of each staking.", - { - startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), - endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), - current: z - .number() - .int() - .min(1) - .default(1) - .optional() - .describe("Currently querying page. Start from 1. Default: 1"), - size: z - .number() - .int() - .min(1) - .max(100) - .default(10) - .optional() - .describe("Number of results per page. Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolStakingHistory({ - ...(params.startTime !== undefined && { startTime: params.startTime }), - ...(params.endTime !== undefined && { endTime: params.endTime }), - ...(params.current !== undefined && { current: params.current }), - ...(params.size !== undefined && { size: params.size }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + startTime: z.number().int().optional().describe("Start time in milliseconds (optional)"), + endTime: z.number().int().optional().describe("End time in milliseconds (optional)"), + current: z + .number() + .int() + .min(1) + .default(1) + .optional() + .describe("Currently querying page. Start from 1. Default: 1"), + size: z + .number() + .int() + .min(1) + .max(100) + .default(10) + .optional() + .describe("Number of results per page. Default: 10, Max: 100"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolStakingHistory({ + ...(params.startTime !== undefined && { startTime: params.startTime }), + ...(params.endTime !== undefined && { endTime: params.endTime }), + ...(params.current !== undefined && { current: params.current }), + ...(params.size !== undefined && { size: params.size }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved SOL staking history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved SOL staking history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL staking history. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL staking history. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts b/src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts index ce5df6e9..0caf796c 100644 --- a/src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts +++ b/src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts @@ -1,43 +1,49 @@ // src/tools/binance-staking/SOL-staking-api/getSolStakingQuotaDetails.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetSolStakingQuotaDetails(server: McpServer) { - server.tool( - "getSolStakingQuotaDetails", + server.registerTool( + "getSolStakingQuotaDetails", + { + description: "Get SOL Staking Quota API allows users to retrieve their current SOL staking quota, including information such as the remaining staking and redemption limits, minimum staking and redeem amounts, commission fees, and the status of staking and redemption availability.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getSolStakingQuotaDetails({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getSolStakingQuotaDetails({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved current SOL staking quota. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved current SOL staking quota. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve current SOL staking quota. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve current SOL staking quota. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts b/src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts index 67bee5c5..ae1c5241 100644 --- a/src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts +++ b/src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetUnclaimedRewards(server: McpServer) { - server.tool( - "BinanceGetUnclaimedRewards", + server.registerTool( + "BinanceGetUnclaimedRewards", + { + description: "Get Unclaimed Rewards API allows users to retrieve information about unclaimed rewards from their SOL staking activities.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.getUnclaimedRewards({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.getUnclaimedRewards({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved information about unclaimed rewards. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved information about unclaimed rewards. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve information about unclaimed rewards. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve information about unclaimed rewards. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/index.ts b/src/tools/binance-staking/SOL-staking-api/index.ts index cd12159d..1485119d 100644 --- a/src/tools/binance-staking/SOL-staking-api/index.ts +++ b/src/tools/binance-staking/SOL-staking-api/index.ts @@ -1,5 +1,6 @@ // src/tools/binance-staking/SOL-staking-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceClaimBoostRewards } from "./claimBoostRewards.js"; import { registerBinanceGetBnsolRateHistory } from "./getBnsolRateHistory.js"; import { registerBinanceGetBnsolRewardsHistory } from "./getBnsolRewardsHistory.js"; @@ -13,15 +14,15 @@ import { registerBinanceSolStakingAccount } from "./solStakingAccount.js"; import { registerBinanceSubscribeSolStaking } from "./subscribeSolStaking.js"; export function registerBinanceSOLStakingApiTools(server: McpServer) { - registerBinanceClaimBoostRewards(server); - registerBinanceGetBnsolRateHistory(server); - registerBinanceGetBnsolRewardsHistory(server); - registerBinanceGetBoostRewardsHistory(server); - registerBinanceGetSolRedemptionHistory(server); - registerBinanceGetSolStakingHistory(server); - registerBinanceGetSolStakingQuotaDetails(server); - registerBinanceGetUnclaimedRewards(server); - registerBinanceRedeemSol(server); - registerBinanceSolStakingAccount(server); - registerBinanceSubscribeSolStaking(server); + registerBinanceClaimBoostRewards(server); + registerBinanceGetBnsolRateHistory(server); + registerBinanceGetBnsolRewardsHistory(server); + registerBinanceGetBoostRewardsHistory(server); + registerBinanceGetSolRedemptionHistory(server); + registerBinanceGetSolStakingHistory(server); + registerBinanceGetSolStakingQuotaDetails(server); + registerBinanceGetUnclaimedRewards(server); + registerBinanceRedeemSol(server); + registerBinanceSolStakingAccount(server); + registerBinanceSubscribeSolStaking(server); } diff --git a/src/tools/binance-staking/SOL-staking-api/redeemSol.ts b/src/tools/binance-staking/SOL-staking-api/redeemSol.ts index fa98b3b1..49b98bb8 100644 --- a/src/tools/binance-staking/SOL-staking-api/redeemSol.ts +++ b/src/tools/binance-staking/SOL-staking-api/redeemSol.ts @@ -1,47 +1,57 @@ // src/tools/binance-staking/SOL-staking-api/getUnclaimedRewards.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceRedeemSol(server: McpServer) { - server.tool( - "registerBinanceRedeemSol", + server.registerTool( + "registerBinanceRedeemSol", + { + description: " Redeem SOL API allows users to redeem BNSOL and receive SOL in exchange. It enables the conversion of BNSOL tokens into SOL based on the specified amount", - { - amount: z.number().min(0).max(99999999).describe("Amount in BNSOL, limit to 8 decimals (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.redeemSol({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z + .number() + .min(0) + .max(99999999) + .describe("Amount in BNSOL, limit to 8 decimals (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.redeemSol({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully redeem BNSOL and receive SOL in exchange. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully redeem BNSOL and receive SOL in exchange. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to redeem BNSOL and receive SOL in exchange. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to redeem BNSOL and receive SOL in exchange. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts b/src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts index 17506fb6..54f9a305 100644 --- a/src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts +++ b/src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts @@ -1,43 +1,49 @@ // src/tools/binance-staking/SOL-staking-api/solStakingAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSolStakingAccount(server: McpServer) { - server.tool( - "registerBinanceSolStakingAccount", + server.registerTool( + "registerBinanceSolStakingAccount", + { + description: "SOL Staking Account API allows users to view their SOL staking account details, including their current BNSOL holdings, equivalent SOL balance, and the profit in SOL over the past 30 days.", - { - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.solStakingAccount({ - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.solStakingAccount({ + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieve SOL staking account details: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieve SOL staking account details: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve SOL staking account details. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve SOL staking account details. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts b/src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts index 65fded66..853b3a46 100644 --- a/src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts +++ b/src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts @@ -1,45 +1,51 @@ // src/tools/binance-staking/SOL-staking-api/subscribeSolStaking.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { stakingClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { stakingClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubscribeSolStaking(server: McpServer) { - server.tool( - "BinanceSubscribeSolStaking", + server.registerTool( + "BinanceSubscribeSolStaking", + { + description: "Subscribe SOL Staking API allows users to stake SOL and receive BNSOL in return. This endpoint requires specifying the amount of SOL to stake, and the response includes the equivalent BNSOL amount and exchange rate for SOL to BNSOL.", - { - amount: z.number().min(0).describe("Amount in SOL (mandatory)"), - recvWindow: z.number().int().optional().describe("Time window for request validity") - }, - async (params) => { - try { - const response = await stakingClient.restAPI.subscribeSolStaking({ - amount: params.amount, - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + amount: z.number().min(0).describe("Amount in SOL (mandatory)"), + recvWindow: z.number().int().optional().describe("Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await stakingClient.restAPI.subscribeSolStaking({ + amount: params.amount, + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully stake SOL and receive BNSOL in return: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully stake SOL and receive BNSOL in return: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to stake SOL. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to stake SOL. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-staking/index.ts b/src/tools/binance-staking/index.ts index 7c594983..b96f673e 100644 --- a/src/tools/binance-staking/index.ts +++ b/src/tools/binance-staking/index.ts @@ -1,9 +1,10 @@ // src/tools/binance-staking/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceETHStakingApiTools } from "./ETH-staking-api/index.js"; import { registerBinanceSOLStakingApiTools } from "./SOL-staking-api/index.js"; export function registerBinanceStakingTools(server: McpServer) { - registerBinanceETHStakingApiTools(server); - registerBinanceSOLStakingApiTools(server); + registerBinanceETHStakingApiTools(server); + registerBinanceSOLStakingApiTools(server); } diff --git a/src/tools/binance-sub-account/assets-api/getFuturesAssetsSummary.ts b/src/tools/binance-sub-account/assets-api/getFuturesAssetsSummary.ts index 736671e7..934e3cd6 100644 --- a/src/tools/binance-sub-account/assets-api/getFuturesAssetsSummary.ts +++ b/src/tools/binance-sub-account/assets-api/getFuturesAssetsSummary.ts @@ -5,42 +5,51 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/getFuturesAssetsSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountFuturesSummary(server: McpServer) { - server.tool( - "BinanceSubAccountFuturesSummary", + server.registerTool( + "BinanceSubAccountFuturesSummary", + { + description: "Get futures account summary for all sub-accounts. Returns total initial margin, maintenance margin, and unrealized PnL.", - { - futuresType: z.enum(["1", "2"]).optional() - .describe("Futures type: 1 for USD-M, 2 for COIN-M"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountFuturesAccountSummaryV2({ - ...(params.futuresType && { futuresType: params.futuresType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + futuresType: z + .enum(["1", "2"]) + .optional() + .describe("Futures type: 1 for USD-M, 2 for COIN-M"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountFuturesAccountSummaryV2({ + ...(params.futuresType && { futuresType: params.futuresType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Futures Summary:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Futures Summary:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get futures summary: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get futures summary: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/assets-api/getFuturesPositionRisk.ts b/src/tools/binance-sub-account/assets-api/getFuturesPositionRisk.ts index 6ca56b71..aa1b6e19 100644 --- a/src/tools/binance-sub-account/assets-api/getFuturesPositionRisk.ts +++ b/src/tools/binance-sub-account/assets-api/getFuturesPositionRisk.ts @@ -5,45 +5,53 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/getFuturesPositionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountFuturesPositionRisk(server: McpServer) { - server.tool( - "BinanceSubAccountFuturesPositionRisk", + server.registerTool( + "BinanceSubAccountFuturesPositionRisk", + { + description: "Get futures position risk for a sub-account. Shows all open positions with entry price, leverage, unrealized PnL, and liquidation price.", - { - email: z.string().email() - .describe("Sub-account email to query position risk for"), - futuresType: z.enum(["1", "2"]).optional() - .describe("Futures type: 1 for USD-M, 2 for COIN-M"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountFuturesPositionRiskV2({ - email: params.email, - ...(params.futuresType && { futuresType: params.futuresType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to query position risk for"), + futuresType: z + .enum(["1", "2"]) + .optional() + .describe("Futures type: 1 for USD-M, 2 for COIN-M"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountFuturesPositionRiskV2({ + email: params.email, + ...(params.futuresType && { futuresType: params.futuresType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Futures Position Risk for ${params.email}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Futures Position Risk for ${params.email}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get position risk: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get position risk: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/assets-api/getMarginAssetsSummary.ts b/src/tools/binance-sub-account/assets-api/getMarginAssetsSummary.ts index 0f7aaa9b..1e94228a 100644 --- a/src/tools/binance-sub-account/assets-api/getMarginAssetsSummary.ts +++ b/src/tools/binance-sub-account/assets-api/getMarginAssetsSummary.ts @@ -5,39 +5,46 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/getMarginAssetsSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountMarginSummary(server: McpServer) { - server.tool( - "BinanceSubAccountMarginSummary", + server.registerTool( + "BinanceSubAccountMarginSummary", + { + description: "Get margin account summary for all sub-accounts. Returns margin level, total assets, and liability information.", - { - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountMarginAccountSummary({ - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountMarginAccountSummary({ + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Margin Summary:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Margin Summary:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get margin summary: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get margin summary: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/assets-api/getSpotAssetsSummary.ts b/src/tools/binance-sub-account/assets-api/getSpotAssetsSummary.ts index c15a3a2d..ec30df0c 100644 --- a/src/tools/binance-sub-account/assets-api/getSpotAssetsSummary.ts +++ b/src/tools/binance-sub-account/assets-api/getSpotAssetsSummary.ts @@ -5,48 +5,58 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/getSpotAssetsSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountSpotSummary(server: McpServer) { - server.tool( - "BinanceSubAccountSpotSummary", + server.registerTool( + "BinanceSubAccountSpotSummary", + { + description: "Get spot account summary for all sub-accounts. Returns aggregated BTC value of all sub-account spot wallets.", - { - email: z.string().email().optional() - .describe("Filter by specific sub-account email"), - page: z.number().int().min(1).optional() - .describe("Page number (starts from 1)"), - size: z.number().int().min(1).max(20).optional() - .describe("Number of results per page (max 20)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.querySubAccountSpotAssetsSummary({ - ...(params.email && { email: params.email }), - ...(params.page && { page: params.page }), - ...(params.size && { size: params.size }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().optional().describe("Filter by specific sub-account email"), + page: z.number().int().min(1).optional().describe("Page number (starts from 1)"), + size: z + .number() + .int() + .min(1) + .max(20) + .optional() + .describe("Number of results per page (max 20)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.querySubAccountSpotAssetsSummary({ + ...(params.email && { email: params.email }), + ...(params.page && { page: params.page }), + ...(params.size && { size: params.size }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Spot Assets Summary:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Spot Assets Summary:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get spot summary: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get spot summary: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/assets-api/getSubAccountAssets.ts b/src/tools/binance-sub-account/assets-api/getSubAccountAssets.ts index b98d5c16..e327c9a5 100644 --- a/src/tools/binance-sub-account/assets-api/getSubAccountAssets.ts +++ b/src/tools/binance-sub-account/assets-api/getSubAccountAssets.ts @@ -5,42 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/getSubAccountAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountAssets(server: McpServer) { - server.tool( - "BinanceSubAccountAssets", + server.registerTool( + "BinanceSubAccountAssets", + { + description: "Get detailed asset balances for a specific sub-account. Shows all tokens and their free/locked amounts.", - { - email: z.string().email() - .describe("Sub-account email to query assets for"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.querySubAccountAssetsV4({ - email: params.email, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to query assets for"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.querySubAccountAssetsV4({ + email: params.email, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Assets for ${params.email}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Assets for ${params.email}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get sub-account assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get sub-account assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/assets-api/index.ts b/src/tools/binance-sub-account/assets-api/index.ts index d1c426f2..31ccd8e5 100644 --- a/src/tools/binance-sub-account/assets-api/index.ts +++ b/src/tools/binance-sub-account/assets-api/index.ts @@ -5,17 +5,18 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/assets-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubAccountAssets } from "./getSubAccountAssets.js"; -import { registerBinanceSubAccountSpotSummary } from "./getSpotAssetsSummary.js"; -import { registerBinanceSubAccountMarginSummary } from "./getMarginAssetsSummary.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSubAccountFuturesSummary } from "./getFuturesAssetsSummary.js"; import { registerBinanceSubAccountFuturesPositionRisk } from "./getFuturesPositionRisk.js"; +import { registerBinanceSubAccountMarginSummary } from "./getMarginAssetsSummary.js"; +import { registerBinanceSubAccountSpotSummary } from "./getSpotAssetsSummary.js"; +import { registerBinanceSubAccountAssets } from "./getSubAccountAssets.js"; export function registerBinanceSubAccountAssetsTools(server: McpServer) { - registerBinanceSubAccountAssets(server); - registerBinanceSubAccountSpotSummary(server); - registerBinanceSubAccountMarginSummary(server); - registerBinanceSubAccountFuturesSummary(server); - registerBinanceSubAccountFuturesPositionRisk(server); + registerBinanceSubAccountAssets(server); + registerBinanceSubAccountSpotSummary(server); + registerBinanceSubAccountMarginSummary(server); + registerBinanceSubAccountFuturesSummary(server); + registerBinanceSubAccountFuturesPositionRisk(server); } diff --git a/src/tools/binance-sub-account/createApiKey.ts b/src/tools/binance-sub-account/createApiKey.ts index 2c49bc1b..ef533aa4 100644 --- a/src/tools/binance-sub-account/createApiKey.ts +++ b/src/tools/binance-sub-account/createApiKey.ts @@ -1,45 +1,50 @@ // src/tools/binance-sub-account/createApiKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountCreateApiKey(server: McpServer) { - server.tool( - "BinanceSubAccountCreateApiKey", - "Create API key for a sub-account.", - { - subAccountId: z.string().describe("Sub-account ID"), - canTrade: z.boolean().describe("Enable spot and margin trading"), - marginTrade: z.boolean().optional().describe("Enable margin loan, repay and transfer"), - futuresTrade: z.boolean().optional().describe("Enable futures trading"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, canTrade, marginTrade, futuresTrade, recvWindow }) => { - try { - const params: any = { subAccountId, canTrade }; - if (marginTrade !== undefined) params.marginTrade = marginTrade; - if (futuresTrade !== undefined) params.futuresTrade = futuresTrade; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.createSubAccountApiKey(params); + server.registerTool( + "BinanceSubAccountCreateApiKey", + { + description: "Create API key for a sub-account.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + canTrade: z.boolean().describe("Enable spot and margin trading"), + marginTrade: z.boolean().optional().describe("Enable margin loan, repay and transfer"), + futuresTrade: z.boolean().optional().describe("Enable futures trading"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, canTrade, marginTrade, futuresTrade, recvWindow }) => { + try { + const params: any = { subAccountId, canTrade }; + if (marginTrade !== undefined) params.marginTrade = marginTrade; + if (futuresTrade !== undefined) params.futuresTrade = futuresTrade; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.createSubAccountApiKey(params); + + return { + content: [ + { + type: "text", + text: `API key created for sub-account. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `API key created for sub-account. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create sub-account API key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create sub-account API key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/createVirtualSubAccount.ts b/src/tools/binance-sub-account/createVirtualSubAccount.ts index c5b6746b..8b7938f7 100644 --- a/src/tools/binance-sub-account/createVirtualSubAccount.ts +++ b/src/tools/binance-sub-account/createVirtualSubAccount.ts @@ -1,40 +1,46 @@ // src/tools/binance-sub-account/createVirtualSubAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountCreateVirtual(server: McpServer) { - server.tool( - "BinanceSubAccountCreateVirtual", + server.registerTool( + "BinanceSubAccountCreateVirtual", + { + description: "Create a virtual sub-account under the master account. Requires master account API key.", - { - subAccountString: z.string().describe("The email address for the virtual sub-account"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountString, recvWindow }) => { - try { - const params: any = { subAccountString }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.createVirtualSubAccount(params); + inputSchema: { + subAccountString: z.string().describe("The email address for the virtual sub-account"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountString, recvWindow }) => { + try { + const params: any = { subAccountString }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.createVirtualSubAccount(params); + + return { + content: [ + { + type: "text", + text: `Virtual sub-account created: ${subAccountString}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Virtual sub-account created: ${subAccountString}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to create virtual sub-account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to create virtual sub-account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/deleteApiKey.ts b/src/tools/binance-sub-account/deleteApiKey.ts index c14ea3fa..80674457 100644 --- a/src/tools/binance-sub-account/deleteApiKey.ts +++ b/src/tools/binance-sub-account/deleteApiKey.ts @@ -1,41 +1,46 @@ // src/tools/binance-sub-account/deleteApiKey.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountDeleteApiKey(server: McpServer) { - server.tool( - "BinanceSubAccountDeleteApiKey", - "Delete API key for a sub-account.", - { - subAccountId: z.string().describe("Sub-account ID"), - subAccountApiKey: z.string().describe("API key to delete"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, subAccountApiKey, recvWindow }) => { - try { - const params: any = { subAccountId, subAccountApiKey }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.deleteSubAccountApiKey(params); + server.registerTool( + "BinanceSubAccountDeleteApiKey", + { + description: "Delete API key for a sub-account.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + subAccountApiKey: z.string().describe("API key to delete"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, subAccountApiKey, recvWindow }) => { + try { + const params: any = { subAccountId, subAccountApiKey }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.deleteSubAccountApiKey(params); + + return { + content: [ + { + type: "text", + text: `API key deleted for sub-account. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `API key deleted for sub-account. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to delete sub-account API key: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to delete sub-account API key: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/deposit-api/getDepositAddress.ts b/src/tools/binance-sub-account/deposit-api/getDepositAddress.ts index 09ed01a7..f676b331 100644 --- a/src/tools/binance-sub-account/deposit-api/getDepositAddress.ts +++ b/src/tools/binance-sub-account/deposit-api/getDepositAddress.ts @@ -5,48 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/deposit-api/getDepositAddress.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountDepositAddress(server: McpServer) { - server.tool( - "BinanceSubAccountDepositAddress", + server.registerTool( + "BinanceSubAccountDepositAddress", + { + description: "Get deposit address for a sub-account. Returns the address and tag/memo if required for the specified asset and network.", - { - email: z.string().email() - .describe("Sub-account email to get deposit address for"), - coin: z.string() - .describe("Coin/asset to get deposit address for (e.g., 'BTC', 'ETH')"), - network: z.string().optional() - .describe("Network (e.g., 'BTC', 'ETH', 'TRX', 'BSC')"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountDepositAddress({ - email: params.email, - coin: params.coin, - ...(params.network && { network: params.network }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to get deposit address for"), + coin: z.string().describe("Coin/asset to get deposit address for (e.g., 'BTC', 'ETH')"), + network: z.string().optional().describe("Network (e.g., 'BTC', 'ETH', 'TRX', 'BSC')"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountDepositAddress({ + email: params.email, + coin: params.coin, + ...(params.network && { network: params.network }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Deposit Address for ${params.email}:\n\nCoin: ${params.coin}\nNetwork: ${params.network || "Default"}\nAddress: ${data.address}\n${data.tag ? `Tag/Memo: ${data.tag}` : ""}\n\n⚠️ Always verify the address before sending funds!`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Deposit Address for ${params.email}:\n\nCoin: ${params.coin}\nNetwork: ${params.network || 'Default'}\nAddress: ${data.address}\n${data.tag ? `Tag/Memo: ${data.tag}` : ''}\n\n⚠️ Always verify the address before sending funds!` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get deposit address: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get deposit address: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/deposit-api/getDepositHistory.ts b/src/tools/binance-sub-account/deposit-api/getDepositHistory.ts index ca80d762..8f6656a5 100644 --- a/src/tools/binance-sub-account/deposit-api/getDepositHistory.ts +++ b/src/tools/binance-sub-account/deposit-api/getDepositHistory.ts @@ -5,60 +5,69 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/deposit-api/getDepositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountDepositHistory(server: McpServer) { - server.tool( - "BinanceSubAccountDepositHistory", + server.registerTool( + "BinanceSubAccountDepositHistory", + { + description: "Get deposit history for a sub-account. Shows all incoming deposits with status, txid, and confirmation details.", - { - email: z.string().email() - .describe("Sub-account email to get deposit history for"), - coin: z.string().optional() - .describe("Filter by specific coin"), - status: z.enum(["0", "1", "6"]).optional() - .describe("Filter by status: 0 = pending, 1 = success, 6 = credited but cannot withdraw"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - limit: z.number().int().min(1).max(1000).optional() - .describe("Number of results (max 1000)"), - offset: z.number().int().optional() - .describe("Offset for pagination"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountDepositHistory({ - email: params.email, - ...(params.coin && { coin: params.coin }), - ...(params.status && { status: params.status }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.offset && { offset: params.offset }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to get deposit history for"), + coin: z.string().optional().describe("Filter by specific coin"), + status: z + .enum(["0", "1", "6"]) + .optional() + .describe("Filter by status: 0 = pending, 1 = success, 6 = credited but cannot withdraw"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Number of results (max 1000)"), + offset: z.number().int().optional().describe("Offset for pagination"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountDepositHistory({ + email: params.email, + ...(params.coin && { coin: params.coin }), + ...(params.status && { status: params.status }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.offset && { offset: params.offset }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Deposit History for ${params.email}:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Deposit History for ${params.email}:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get deposit history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/deposit-api/index.ts b/src/tools/binance-sub-account/deposit-api/index.ts index 390a06ce..88924663 100644 --- a/src/tools/binance-sub-account/deposit-api/index.ts +++ b/src/tools/binance-sub-account/deposit-api/index.ts @@ -5,11 +5,12 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/deposit-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSubAccountDepositAddress } from "./getDepositAddress.js"; import { registerBinanceSubAccountDepositHistory } from "./getDepositHistory.js"; export function registerBinanceSubAccountDepositTools(server: McpServer) { - registerBinanceSubAccountDepositAddress(server); - registerBinanceSubAccountDepositHistory(server); + registerBinanceSubAccountDepositAddress(server); + registerBinanceSubAccountDepositHistory(server); } diff --git a/src/tools/binance-sub-account/enableFutures.ts b/src/tools/binance-sub-account/enableFutures.ts index 11aa84da..4d283701 100644 --- a/src/tools/binance-sub-account/enableFutures.ts +++ b/src/tools/binance-sub-account/enableFutures.ts @@ -1,40 +1,45 @@ // src/tools/binance-sub-account/enableFutures.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountEnableFutures(server: McpServer) { - server.tool( - "BinanceSubAccountEnableFutures", - "Enable futures trading for a sub-account.", - { - email: z.string().describe("Sub-account email"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = { email }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.enableFuturesForSubAccount(params); + server.registerTool( + "BinanceSubAccountEnableFutures", + { + description: "Enable futures trading for a sub-account.", + inputSchema: { + email: z.string().describe("Sub-account email"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = { email }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.enableFuturesForSubAccount(params); + + return { + content: [ + { + type: "text", + text: `Futures enabled for sub-account ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Futures enabled for sub-account ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to enable futures for sub-account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to enable futures for sub-account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/enableMargin.ts b/src/tools/binance-sub-account/enableMargin.ts index 859c8411..9747f3c2 100644 --- a/src/tools/binance-sub-account/enableMargin.ts +++ b/src/tools/binance-sub-account/enableMargin.ts @@ -1,40 +1,45 @@ // src/tools/binance-sub-account/enableMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountEnableMargin(server: McpServer) { - server.tool( - "BinanceSubAccountEnableMargin", - "Enable margin trading for a sub-account.", - { - email: z.string().describe("Sub-account email"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = { email }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.enableMarginForSubAccount(params); + server.registerTool( + "BinanceSubAccountEnableMargin", + { + description: "Enable margin trading for a sub-account.", + inputSchema: { + email: z.string().describe("Sub-account email"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = { email }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.enableMarginForSubAccount(params); + + return { + content: [ + { + type: "text", + text: `Margin enabled for sub-account ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Margin enabled for sub-account ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to enable margin for sub-account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to enable margin for sub-account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getApiKeyIpRestriction.ts b/src/tools/binance-sub-account/getApiKeyIpRestriction.ts index efe78204..e39fce1d 100644 --- a/src/tools/binance-sub-account/getApiKeyIpRestriction.ts +++ b/src/tools/binance-sub-account/getApiKeyIpRestriction.ts @@ -1,41 +1,44 @@ // src/tools/binance-sub-account/getApiKeyIpRestriction.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetApiKeyIpRestriction(server: McpServer) { - server.tool( - "BinanceSubAccountGetApiKeyIpRestriction", - "Get IP restriction for a sub-account API key.", - { - subAccountId: z.string().describe("Sub-account ID"), - subAccountApiKey: z.string().describe("Sub-account API key"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, subAccountApiKey, recvWindow }) => { - try { - const params: any = { subAccountId, subAccountApiKey }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountApiKeyIpRestriction(params); + server.registerTool( + "BinanceSubAccountGetApiKeyIpRestriction", + { + description: "Get IP restriction for a sub-account API key.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + subAccountApiKey: z.string().describe("Sub-account API key"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, subAccountApiKey, recvWindow }) => { + try { + const params: any = { subAccountId, subAccountApiKey }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountApiKeyIpRestriction(params); + + return { + content: [ + { + type: "text", + text: `Retrieved IP restriction for sub-account API key. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved IP restriction for sub-account API key. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get IP restriction: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get IP restriction: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountAssets.ts b/src/tools/binance-sub-account/getSubAccountAssets.ts index 6c36f1f6..1b16d3f4 100644 --- a/src/tools/binance-sub-account/getSubAccountAssets.ts +++ b/src/tools/binance-sub-account/getSubAccountAssets.ts @@ -1,40 +1,43 @@ // src/tools/binance-sub-account/getSubAccountAssets.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetAssets(server: McpServer) { - server.tool( - "BinanceSubAccountGetAssets", - "Query sub-account assets (balances).", - { - email: z.string().describe("Sub-account email"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = { email }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountAssets(params); + server.registerTool( + "BinanceSubAccountGetAssets", + { + description: "Query sub-account assets (balances).", + inputSchema: { + email: z.string().describe("Sub-account email"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = { email }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountAssets(params); + + return { + content: [ + { + type: "text", + text: `Retrieved assets for sub-account ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved assets for sub-account ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get sub-account assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountDepositAddress.ts b/src/tools/binance-sub-account/getSubAccountDepositAddress.ts index c84b357a..7a6a6f35 100644 --- a/src/tools/binance-sub-account/getSubAccountDepositAddress.ts +++ b/src/tools/binance-sub-account/getSubAccountDepositAddress.ts @@ -1,43 +1,48 @@ // src/tools/binance-sub-account/getSubAccountDepositAddress.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetDepositAddress(server: McpServer) { - server.tool( - "BinanceSubAccountGetDepositAddress", - "Get sub-account deposit address for a specific coin.", - { - email: z.string().describe("Sub-account email"), - coin: z.string().describe("Coin to get deposit address for (e.g., BTC, ETH)"), - network: z.string().optional().describe("Network to use (e.g., BTC, ETH, BSC)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, coin, network, recvWindow }) => { - try { - const params: any = { email, coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountDepositAddress(params); + server.registerTool( + "BinanceSubAccountGetDepositAddress", + { + description: "Get sub-account deposit address for a specific coin.", + inputSchema: { + email: z.string().describe("Sub-account email"), + coin: z.string().describe("Coin to get deposit address for (e.g., BTC, ETH)"), + network: z.string().optional().describe("Network to use (e.g., BTC, ETH, BSC)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, coin, network, recvWindow }) => { + try { + const params: any = { email, coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountDepositAddress(params); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit address for ${coin} on ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit address for ${coin} on ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account deposit address: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account deposit address: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountDepositHistory.ts b/src/tools/binance-sub-account/getSubAccountDepositHistory.ts index 475366b5..cfbb2903 100644 --- a/src/tools/binance-sub-account/getSubAccountDepositHistory.ts +++ b/src/tools/binance-sub-account/getSubAccountDepositHistory.ts @@ -1,52 +1,60 @@ // src/tools/binance-sub-account/getSubAccountDepositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetDepositHistory(server: McpServer) { - server.tool( - "BinanceSubAccountGetDepositHistory", - "Query sub-account deposit history.", - { - email: z.string().describe("Sub-account email"), - coin: z.string().optional().describe("Coin to filter by"), - status: z.number().optional().describe("0: pending, 6: credited but cannot withdraw, 1: success"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500, max 500"), - offset: z.number().optional().describe("Default 0"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, coin, status, startTime, endTime, limit, offset, recvWindow }) => { - try { - const params: any = { email }; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (offset !== undefined) params.offset = offset; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountDepositHistory(params); + server.registerTool( + "BinanceSubAccountGetDepositHistory", + { + description: "Query sub-account deposit history.", + inputSchema: { + email: z.string().describe("Sub-account email"), + coin: z.string().optional().describe("Coin to filter by"), + status: z + .number() + .optional() + .describe("0: pending, 6: credited but cannot withdraw, 1: success"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500, max 500"), + offset: z.number().optional().describe("Default 0"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, coin, status, startTime, endTime, limit, offset, recvWindow }) => { + try { + const params: any = { email }; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (offset !== undefined) params.offset = offset; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountDepositHistory(params); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit history for ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit history for ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account deposit history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account deposit history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountFuturesPositionRisk.ts b/src/tools/binance-sub-account/getSubAccountFuturesPositionRisk.ts index 0b4fd5ef..105312bb 100644 --- a/src/tools/binance-sub-account/getSubAccountFuturesPositionRisk.ts +++ b/src/tools/binance-sub-account/getSubAccountFuturesPositionRisk.ts @@ -1,42 +1,53 @@ // src/tools/binance-sub-account/getSubAccountFuturesPositionRisk.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetFuturesPositionRisk(server: McpServer) { - server.tool( - "BinanceSubAccountGetFuturesPositionRisk", - "Query sub-account futures position risk.", - { - email: z.string().describe("Sub-account email"), - futuresType: z.number().optional().describe("1: USDT Margined Futures, 2: COIN Margined Futures"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, futuresType, recvWindow }) => { - try { - const params: any = { email }; - if (futuresType !== undefined) params.futuresType = futuresType; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountFuturesPositionRisk(params); + server.registerTool( + "BinanceSubAccountGetFuturesPositionRisk", + { + description: "Query sub-account futures position risk.", + inputSchema: { + email: z.string().describe("Sub-account email"), + futuresType: z + .number() + .optional() + .describe("1: USDT Margined Futures, 2: COIN Margined Futures"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, futuresType, recvWindow }) => { + try { + const params: any = { email }; + if (futuresType !== undefined) params.futuresType = futuresType; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountFuturesPositionRisk(params); + + return { + content: [ + { + type: "text", + text: `Retrieved futures position risk for ${email}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved futures position risk for ${email}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account futures position risk: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to get sub-account futures position risk: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountFuturesSummary.ts b/src/tools/binance-sub-account/getSubAccountFuturesSummary.ts index ceb11fc1..e372c430 100644 --- a/src/tools/binance-sub-account/getSubAccountFuturesSummary.ts +++ b/src/tools/binance-sub-account/getSubAccountFuturesSummary.ts @@ -1,41 +1,46 @@ // src/tools/binance-sub-account/getSubAccountFuturesSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetFuturesSummary(server: McpServer) { - server.tool( - "BinanceSubAccountGetFuturesSummary", - "Query sub-account futures account summary.", - { - email: z.string().optional().describe("Sub-account email (optional)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = {}; - if (email !== undefined) params.email = email; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountFuturesSummary(params); + server.registerTool( + "BinanceSubAccountGetFuturesSummary", + { + description: "Query sub-account futures account summary.", + inputSchema: { + email: z.string().optional().describe("Sub-account email (optional)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = {}; + if (email !== undefined) params.email = email; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountFuturesSummary(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account futures summary. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account futures summary. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account futures summary: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account futures summary: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountList.ts b/src/tools/binance-sub-account/getSubAccountList.ts index a177c3dd..c2cf3c2e 100644 --- a/src/tools/binance-sub-account/getSubAccountList.ts +++ b/src/tools/binance-sub-account/getSubAccountList.ts @@ -1,47 +1,50 @@ // src/tools/binance-sub-account/getSubAccountList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetList(server: McpServer) { - server.tool( - "BinanceSubAccountGetList", - "Query the list of sub-accounts under the master account.", - { - email: z.string().optional().describe("Sub-account email to filter"), - isFreeze: z.string().optional().describe("Filter by freeze status: 'true' or 'false'"), - page: z.number().optional().describe("Page number, default 1"), - limit: z.number().optional().describe("Results per page, default 1, max 200"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, isFreeze, page, limit, recvWindow }) => { - try { - const params: any = {}; - if (email !== undefined) params.email = email; - if (isFreeze !== undefined) params.isFreeze = isFreeze; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountList(params); + server.registerTool( + "BinanceSubAccountGetList", + { + description: "Query the list of sub-accounts under the master account.", + inputSchema: { + email: z.string().optional().describe("Sub-account email to filter"), + isFreeze: z.string().optional().describe("Filter by freeze status: 'true' or 'false'"), + page: z.number().optional().describe("Page number, default 1"), + limit: z.number().optional().describe("Results per page, default 1, max 200"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, isFreeze, page, limit, recvWindow }) => { + try { + const params: any = {}; + if (email !== undefined) params.email = email; + if (isFreeze !== undefined) params.isFreeze = isFreeze; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountList(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account list. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account list. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get sub-account list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountMarginSummary.ts b/src/tools/binance-sub-account/getSubAccountMarginSummary.ts index 77908a00..a00e307b 100644 --- a/src/tools/binance-sub-account/getSubAccountMarginSummary.ts +++ b/src/tools/binance-sub-account/getSubAccountMarginSummary.ts @@ -1,41 +1,46 @@ // src/tools/binance-sub-account/getSubAccountMarginSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetMarginSummary(server: McpServer) { - server.tool( - "BinanceSubAccountGetMarginSummary", - "Query sub-account margin account summary.", - { - email: z.string().optional().describe("Sub-account email (optional)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = {}; - if (email !== undefined) params.email = email; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountMarginSummary(params); + server.registerTool( + "BinanceSubAccountGetMarginSummary", + { + description: "Query sub-account margin account summary.", + inputSchema: { + email: z.string().optional().describe("Sub-account email (optional)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = {}; + if (email !== undefined) params.email = email; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountMarginSummary(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account margin summary. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account margin summary. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account margin summary: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account margin summary: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountSpotSummary.ts b/src/tools/binance-sub-account/getSubAccountSpotSummary.ts index b713f4c7..ca6399a8 100644 --- a/src/tools/binance-sub-account/getSubAccountSpotSummary.ts +++ b/src/tools/binance-sub-account/getSubAccountSpotSummary.ts @@ -1,45 +1,53 @@ // src/tools/binance-sub-account/getSubAccountSpotSummary.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetSpotSummary(server: McpServer) { - server.tool( - "BinanceSubAccountGetSpotSummary", - "Query sub-account spot assets summary for master account.", - { - email: z.string().optional().describe("Sub-account email (optional, returns all if not provided)"), - page: z.number().optional().describe("Page number, default 1"), - size: z.number().optional().describe("Results per page, default 10, max 20"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, page, size, recvWindow }) => { - try { - const params: any = {}; - if (email !== undefined) params.email = email; - if (page !== undefined) params.page = page; - if (size !== undefined) params.size = size; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountSpotSummary(params); + server.registerTool( + "BinanceSubAccountGetSpotSummary", + { + description: "Query sub-account spot assets summary for master account.", + inputSchema: { + email: z + .string() + .optional() + .describe("Sub-account email (optional, returns all if not provided)"), + page: z.number().optional().describe("Page number, default 1"), + size: z.number().optional().describe("Results per page, default 10, max 20"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, page, size, recvWindow }) => { + try { + const params: any = {}; + if (email !== undefined) params.email = email; + if (page !== undefined) params.page = page; + if (size !== undefined) params.size = size; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountSpotSummary(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account spot summary. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account spot summary. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account spot summary: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account spot summary: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountStatus.ts b/src/tools/binance-sub-account/getSubAccountStatus.ts index 3cedc4dd..55108b8f 100644 --- a/src/tools/binance-sub-account/getSubAccountStatus.ts +++ b/src/tools/binance-sub-account/getSubAccountStatus.ts @@ -1,41 +1,44 @@ // src/tools/binance-sub-account/getSubAccountStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetStatus(server: McpServer) { - server.tool( - "BinanceSubAccountGetStatus", - "Get sub-account status including enable/disable status for margin and futures.", - { - email: z.string().optional().describe("Sub-account email (optional)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, recvWindow }) => { - try { - const params: any = {}; - if (email !== undefined) params.email = email; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountStatus(params); + server.registerTool( + "BinanceSubAccountGetStatus", + { + description: "Get sub-account status including enable/disable status for margin and futures.", + inputSchema: { + email: z.string().optional().describe("Sub-account email (optional)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: any = {}; + if (email !== undefined) params.email = email; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountStatus(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to get sub-account status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getSubAccountTransferHistory.ts b/src/tools/binance-sub-account/getSubAccountTransferHistory.ts index 9ae64481..4477fefa 100644 --- a/src/tools/binance-sub-account/getSubAccountTransferHistory.ts +++ b/src/tools/binance-sub-account/getSubAccountTransferHistory.ts @@ -1,49 +1,54 @@ // src/tools/binance-sub-account/getSubAccountTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetTransferHistory(server: McpServer) { - server.tool( - "BinanceSubAccountGetTransferHistory", - "Query sub-account transfer history.", - { - asset: z.string().optional().describe("Asset to filter by"), - type: z.number().optional().describe("1: transfer in, 2: transfer out"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 500, max 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, type, startTime, endTime, limit, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (type !== undefined) params.type = type; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountTransferHistory(params); + server.registerTool( + "BinanceSubAccountGetTransferHistory", + { + description: "Query sub-account transfer history.", + inputSchema: { + asset: z.string().optional().describe("Asset to filter by"), + type: z.number().optional().describe("1: transfer in, 2: transfer out"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 500, max 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, type, startTime, endTime, limit, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (type !== undefined) params.type = type; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountTransferHistory(params); + + return { + content: [ + { + type: "text", + text: `Retrieved sub-account transfer history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved sub-account transfer history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get sub-account transfer history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get sub-account transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/getUniversalTransferHistory.ts b/src/tools/binance-sub-account/getUniversalTransferHistory.ts index 2a3f24b7..7fc1bfd7 100644 --- a/src/tools/binance-sub-account/getUniversalTransferHistory.ts +++ b/src/tools/binance-sub-account/getUniversalTransferHistory.ts @@ -1,51 +1,56 @@ // src/tools/binance-sub-account/getUniversalTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountGetUniversalTransferHistory(server: McpServer) { - server.tool( - "BinanceSubAccountGetUniversalTransferHistory", - "Query universal transfer history for sub-accounts.", - { - fromEmail: z.string().optional().describe("Sender email"), - toEmail: z.string().optional().describe("Recipient email"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number, default 1"), - limit: z.number().optional().describe("Results per page, default 500, max 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ fromEmail, toEmail, startTime, endTime, page, limit, recvWindow }) => { - try { - const params: any = {}; - if (fromEmail !== undefined) params.fromEmail = fromEmail; - if (toEmail !== undefined) params.toEmail = toEmail; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.getSubAccountUniversalTransferHistory(params); + server.registerTool( + "BinanceSubAccountGetUniversalTransferHistory", + { + description: "Query universal transfer history for sub-accounts.", + inputSchema: { + fromEmail: z.string().optional().describe("Sender email"), + toEmail: z.string().optional().describe("Recipient email"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number, default 1"), + limit: z.number().optional().describe("Results per page, default 500, max 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ fromEmail, toEmail, startTime, endTime, page, limit, recvWindow }) => { + try { + const params: any = {}; + if (fromEmail !== undefined) params.fromEmail = fromEmail; + if (toEmail !== undefined) params.toEmail = toEmail; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.getSubAccountUniversalTransferHistory(params); + + return { + content: [ + { + type: "text", + text: `Retrieved universal transfer history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved universal transfer history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get universal transfer history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to get universal transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/index.ts b/src/tools/binance-sub-account/index.ts index 8d8f5495..22fbbb05 100644 --- a/src/tools/binance-sub-account/index.ts +++ b/src/tools/binance-sub-account/index.ts @@ -1,58 +1,59 @@ // src/tools/binance-sub-account/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceSubAccountCreateApiKey } from "./createApiKey.js"; import { registerBinanceSubAccountCreateVirtual } from "./createVirtualSubAccount.js"; -import { registerBinanceSubAccountGetList } from "./getSubAccountList.js"; +import { registerBinanceSubAccountDeleteApiKey } from "./deleteApiKey.js"; +import { registerBinanceSubAccountEnableFutures } from "./enableFutures.js"; +import { registerBinanceSubAccountEnableMargin } from "./enableMargin.js"; +import { registerBinanceSubAccountGetApiKeyIpRestriction } from "./getApiKeyIpRestriction.js"; import { registerBinanceSubAccountGetAssets } from "./getSubAccountAssets.js"; +import { registerBinanceSubAccountGetDepositAddress } from "./getSubAccountDepositAddress.js"; +import { registerBinanceSubAccountGetDepositHistory } from "./getSubAccountDepositHistory.js"; +import { registerBinanceSubAccountGetFuturesPositionRisk } from "./getSubAccountFuturesPositionRisk.js"; +import { registerBinanceSubAccountGetFuturesSummary } from "./getSubAccountFuturesSummary.js"; +import { registerBinanceSubAccountGetList } from "./getSubAccountList.js"; +import { registerBinanceSubAccountGetMarginSummary } from "./getSubAccountMarginSummary.js"; import { registerBinanceSubAccountGetSpotSummary } from "./getSubAccountSpotSummary.js"; import { registerBinanceSubAccountGetStatus } from "./getSubAccountStatus.js"; -import { registerBinanceSubAccountEnableMargin } from "./enableMargin.js"; -import { registerBinanceSubAccountGetMarginSummary } from "./getSubAccountMarginSummary.js"; -import { registerBinanceSubAccountEnableFutures } from "./enableFutures.js"; -import { registerBinanceSubAccountGetFuturesSummary } from "./getSubAccountFuturesSummary.js"; -import { registerBinanceSubAccountGetFuturesPositionRisk } from "./getSubAccountFuturesPositionRisk.js"; -import { registerBinanceSubAccountTransferToSub } from "./transferToSubAccount.js"; -import { registerBinanceSubAccountTransferToMaster } from "./transferToMaster.js"; import { registerBinanceSubAccountGetTransferHistory } from "./getSubAccountTransferHistory.js"; -import { registerBinanceSubAccountUniversalTransfer } from "./universalTransfer.js"; import { registerBinanceSubAccountGetUniversalTransferHistory } from "./getUniversalTransferHistory.js"; -import { registerBinanceSubAccountGetDepositAddress } from "./getSubAccountDepositAddress.js"; -import { registerBinanceSubAccountGetDepositHistory } from "./getSubAccountDepositHistory.js"; -import { registerBinanceSubAccountCreateApiKey } from "./createApiKey.js"; -import { registerBinanceSubAccountDeleteApiKey } from "./deleteApiKey.js"; +import { registerBinanceSubAccountTransferToMaster } from "./transferToMaster.js"; +import { registerBinanceSubAccountTransferToSub } from "./transferToSubAccount.js"; +import { registerBinanceSubAccountUniversalTransfer } from "./universalTransfer.js"; import { registerBinanceSubAccountUpdateIpRestriction } from "./updateIpRestriction.js"; -import { registerBinanceSubAccountGetApiKeyIpRestriction } from "./getApiKeyIpRestriction.js"; export function registerBinanceSubAccountTools(server: McpServer) { - // Sub-account Management - registerBinanceSubAccountCreateVirtual(server); - registerBinanceSubAccountGetList(server); - registerBinanceSubAccountGetAssets(server); - registerBinanceSubAccountGetSpotSummary(server); - registerBinanceSubAccountGetStatus(server); - - // Margin Management - registerBinanceSubAccountEnableMargin(server); - registerBinanceSubAccountGetMarginSummary(server); - - // Futures Management - registerBinanceSubAccountEnableFutures(server); - registerBinanceSubAccountGetFuturesSummary(server); - registerBinanceSubAccountGetFuturesPositionRisk(server); - - // Transfers - registerBinanceSubAccountTransferToSub(server); - registerBinanceSubAccountTransferToMaster(server); - registerBinanceSubAccountGetTransferHistory(server); - registerBinanceSubAccountUniversalTransfer(server); - registerBinanceSubAccountGetUniversalTransferHistory(server); - - // Deposit - registerBinanceSubAccountGetDepositAddress(server); - registerBinanceSubAccountGetDepositHistory(server); - - // API Key Management - registerBinanceSubAccountCreateApiKey(server); - registerBinanceSubAccountDeleteApiKey(server); - registerBinanceSubAccountUpdateIpRestriction(server); - registerBinanceSubAccountGetApiKeyIpRestriction(server); + // Sub-account Management + registerBinanceSubAccountCreateVirtual(server); + registerBinanceSubAccountGetList(server); + registerBinanceSubAccountGetAssets(server); + registerBinanceSubAccountGetSpotSummary(server); + registerBinanceSubAccountGetStatus(server); + + // Margin Management + registerBinanceSubAccountEnableMargin(server); + registerBinanceSubAccountGetMarginSummary(server); + + // Futures Management + registerBinanceSubAccountEnableFutures(server); + registerBinanceSubAccountGetFuturesSummary(server); + registerBinanceSubAccountGetFuturesPositionRisk(server); + + // Transfers + registerBinanceSubAccountTransferToSub(server); + registerBinanceSubAccountTransferToMaster(server); + registerBinanceSubAccountGetTransferHistory(server); + registerBinanceSubAccountUniversalTransfer(server); + registerBinanceSubAccountGetUniversalTransferHistory(server); + + // Deposit + registerBinanceSubAccountGetDepositAddress(server); + registerBinanceSubAccountGetDepositHistory(server); + + // API Key Management + registerBinanceSubAccountCreateApiKey(server); + registerBinanceSubAccountDeleteApiKey(server); + registerBinanceSubAccountUpdateIpRestriction(server); + registerBinanceSubAccountGetApiKeyIpRestriction(server); } diff --git a/src/tools/binance-sub-account/management-api/createSubAccount.ts b/src/tools/binance-sub-account/management-api/createSubAccount.ts index 991e6fc5..21a2f090 100644 --- a/src/tools/binance-sub-account/management-api/createSubAccount.ts +++ b/src/tools/binance-sub-account/management-api/createSubAccount.ts @@ -5,42 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/createSubAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountCreate(server: McpServer) { - server.tool( - "BinanceSubAccountCreate", + server.registerTool( + "BinanceSubAccountCreate", + { + description: "Create a new virtual sub-account under your master account. Sub-accounts are useful for separating trading strategies or managing funds for different purposes. ⚠️ Requires master account permissions.", - { - subAccountString: z.string().min(1).max(20) - .describe("Sub-account name/label (1-20 characters, alphanumeric)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.createVirtualSubAccount({ - subAccountString: params.subAccountString, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + subAccountString: z + .string() + .min(1) + .max(20) + .describe("Sub-account name/label (1-20 characters, alphanumeric)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.createVirtualSubAccount({ + subAccountString: params.subAccountString, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Sub-account created successfully!\n\nEmail: ${data.email}\n\n📝 Note: The sub-account email is auto-generated. Use it for API operations and transfers.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Sub-account created successfully!\n\nEmail: ${data.email}\n\n📝 Note: The sub-account email is auto-generated. Use it for API operations and transfers.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to create sub-account: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to create sub-account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/enableFutures.ts b/src/tools/binance-sub-account/management-api/enableFutures.ts index e01ef66a..fab4fe95 100644 --- a/src/tools/binance-sub-account/management-api/enableFutures.ts +++ b/src/tools/binance-sub-account/management-api/enableFutures.ts @@ -5,42 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/enableFutures.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountEnableFutures(server: McpServer) { - server.tool( - "BinanceSubAccountEnableFutures", + server.registerTool( + "BinanceSubAccountEnableFutures", + { + description: "Enable futures trading for a sub-account. ⚠️ WARNING: Futures trading involves leverage and carries significant risk of total loss. Only enable if you understand the risks.", - { - email: z.string().email() - .describe("Sub-account email to enable futures for"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.enableFuturesForSubAccount({ - email: params.email, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to enable futures for"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.enableFuturesForSubAccount({ + email: params.email, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Futures trading enabled for sub-account: ${params.email}\n\nResponse: ${JSON.stringify(data, null, 2)}\n\n⚠️ Reminder: Futures trading carries significant risk of total loss.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Futures trading enabled for sub-account: ${params.email}\n\nResponse: ${JSON.stringify(data, null, 2)}\n\n⚠️ Reminder: Futures trading carries significant risk of total loss.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to enable futures: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to enable futures: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/enableMargin.ts b/src/tools/binance-sub-account/management-api/enableMargin.ts index cda0a247..bc62c185 100644 --- a/src/tools/binance-sub-account/management-api/enableMargin.ts +++ b/src/tools/binance-sub-account/management-api/enableMargin.ts @@ -5,42 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/enableMargin.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountEnableMargin(server: McpServer) { - server.tool( - "BinanceSubAccountEnableMargin", + server.registerTool( + "BinanceSubAccountEnableMargin", + { + description: "Enable margin trading for a sub-account. ⚠️ WARNING: Margin trading involves leverage and carries significant risk of loss. Only enable if you understand the risks.", - { - email: z.string().email() - .describe("Sub-account email to enable margin for"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.enableMarginForSubAccount({ - email: params.email, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to enable margin for"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.enableMarginForSubAccount({ + email: params.email, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Margin trading enabled for sub-account: ${params.email}\n\nResponse: ${JSON.stringify(data, null, 2)}\n\n⚠️ Reminder: Margin trading carries significant risk.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Margin trading enabled for sub-account: ${params.email}\n\nResponse: ${JSON.stringify(data, null, 2)}\n\n⚠️ Reminder: Margin trading carries significant risk.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to enable margin: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to enable margin: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/getSubAccountApiPermission.ts b/src/tools/binance-sub-account/management-api/getSubAccountApiPermission.ts index a277c542..677b2246 100644 --- a/src/tools/binance-sub-account/management-api/getSubAccountApiPermission.ts +++ b/src/tools/binance-sub-account/management-api/getSubAccountApiPermission.ts @@ -5,45 +5,50 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/getSubAccountApiPermission.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountApiPermission(server: McpServer) { - server.tool( - "BinanceSubAccountApiPermission", + server.registerTool( + "BinanceSubAccountApiPermission", + { + description: "Get API key permissions for a sub-account. Shows what operations the API key is allowed to perform.", - { - email: z.string().email() - .describe("Sub-account email to query API permissions for"), - subAccountApiKey: z.string() - .describe("Sub-account API key to check permissions for"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountApiIpRestriction({ - email: params.email, - subAccountApiKey: params.subAccountApiKey, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().describe("Sub-account email to query API permissions for"), + subAccountApiKey: z.string().describe("Sub-account API key to check permissions for"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountApiIpRestriction({ + email: params.email, + subAccountApiKey: params.subAccountApiKey, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account API Permissions:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account API Permissions:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get API permissions: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get API permissions: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/getSubAccountList.ts b/src/tools/binance-sub-account/management-api/getSubAccountList.ts index b30713a2..7a4bd347 100644 --- a/src/tools/binance-sub-account/management-api/getSubAccountList.ts +++ b/src/tools/binance-sub-account/management-api/getSubAccountList.ts @@ -5,51 +5,60 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/getSubAccountList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountList(server: McpServer) { - server.tool( - "BinanceSubAccountList", + server.registerTool( + "BinanceSubAccountList", + { + description: "Get a list of all sub-accounts under your master account. Returns email, status, and creation time for each sub-account.", - { - email: z.string().email().optional() - .describe("Filter by specific sub-account email"), - isFreeze: z.enum(["true", "false"]).optional() - .describe("Filter by freeze status"), - page: z.number().int().min(1).optional() - .describe("Page number (starts from 1)"), - limit: z.number().int().min(1).max(200).optional() - .describe("Number of results per page (max 200)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.querySubAccountList({ - ...(params.email && { email: params.email }), - ...(params.isFreeze && { isFreeze: params.isFreeze }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().optional().describe("Filter by specific sub-account email"), + isFreeze: z.enum(["true", "false"]).optional().describe("Filter by freeze status"), + page: z.number().int().min(1).optional().describe("Page number (starts from 1)"), + limit: z + .number() + .int() + .min(1) + .max(200) + .optional() + .describe("Number of results per page (max 200)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.querySubAccountList({ + ...(params.email && { email: params.email }), + ...(params.isFreeze && { isFreeze: params.isFreeze }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account List:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account List:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get sub-account list: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get sub-account list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/getSubAccountStatus.ts b/src/tools/binance-sub-account/management-api/getSubAccountStatus.ts index 90c8483c..20da3f9e 100644 --- a/src/tools/binance-sub-account/management-api/getSubAccountStatus.ts +++ b/src/tools/binance-sub-account/management-api/getSubAccountStatus.ts @@ -5,42 +5,48 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/getSubAccountStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountStatus(server: McpServer) { - server.tool( - "BinanceSubAccountStatus", + server.registerTool( + "BinanceSubAccountStatus", + { + description: "Get the status of a sub-account including enabled features (margin, futures, etc.) and trading permissions.", - { - email: z.string().email().optional() - .describe("Sub-account email to query"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.getSubAccountStatus({ - ...(params.email && { email: params.email }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + email: z.string().email().optional().describe("Sub-account email to query"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.getSubAccountStatus({ + ...(params.email && { email: params.email }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Status:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Status:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get sub-account status: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get sub-account status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/management-api/index.ts b/src/tools/binance-sub-account/management-api/index.ts index 54f56e3b..3f9c70d6 100644 --- a/src/tools/binance-sub-account/management-api/index.ts +++ b/src/tools/binance-sub-account/management-api/index.ts @@ -5,19 +5,20 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/management-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceSubAccountCreate } from "./createSubAccount.js"; -import { registerBinanceSubAccountList } from "./getSubAccountList.js"; -import { registerBinanceSubAccountStatus } from "./getSubAccountStatus.js"; -import { registerBinanceSubAccountEnableMargin } from "./enableMargin.js"; import { registerBinanceSubAccountEnableFutures } from "./enableFutures.js"; +import { registerBinanceSubAccountEnableMargin } from "./enableMargin.js"; import { registerBinanceSubAccountApiPermission } from "./getSubAccountApiPermission.js"; +import { registerBinanceSubAccountList } from "./getSubAccountList.js"; +import { registerBinanceSubAccountStatus } from "./getSubAccountStatus.js"; export function registerBinanceSubAccountManagementTools(server: McpServer) { - registerBinanceSubAccountCreate(server); - registerBinanceSubAccountList(server); - registerBinanceSubAccountStatus(server); - registerBinanceSubAccountEnableMargin(server); - registerBinanceSubAccountEnableFutures(server); - registerBinanceSubAccountApiPermission(server); + registerBinanceSubAccountCreate(server); + registerBinanceSubAccountList(server); + registerBinanceSubAccountStatus(server); + registerBinanceSubAccountEnableMargin(server); + registerBinanceSubAccountEnableFutures(server); + registerBinanceSubAccountApiPermission(server); } diff --git a/src/tools/binance-sub-account/transfer-api/futuresTransfer.ts b/src/tools/binance-sub-account/transfer-api/futuresTransfer.ts index 857dd54c..c97eb85b 100644 --- a/src/tools/binance-sub-account/transfer-api/futuresTransfer.ts +++ b/src/tools/binance-sub-account/transfer-api/futuresTransfer.ts @@ -5,54 +5,56 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/futuresTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountFuturesTransfer(server: McpServer) { - server.tool( - "BinanceSubAccountFuturesTransfer", + server.registerTool( + "BinanceSubAccountFuturesTransfer", + { + description: "Internal transfer between sub-account futures accounts. Move assets between different sub-account futures wallets.", - { - fromEmail: z.string().email() - .describe("Sender sub-account email"), - toEmail: z.string().email() - .describe("Recipient sub-account email"), - futuresType: z.enum(["1", "2"]) - .describe("Futures type: 1 for USD-M, 2 for COIN-M"), - asset: z.string() - .describe("Asset to transfer (e.g., 'USDT', 'BTC')"), - amount: z.number().positive() - .describe("Amount to transfer"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.subAccountFuturesInternalTransfer({ - fromEmail: params.fromEmail, - toEmail: params.toEmail, - futuresType: params.futuresType, - asset: params.asset, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + fromEmail: z.string().email().describe("Sender sub-account email"), + toEmail: z.string().email().describe("Recipient sub-account email"), + futuresType: z.enum(["1", "2"]).describe("Futures type: 1 for USD-M, 2 for COIN-M"), + asset: z.string().describe("Asset to transfer (e.g., 'USDT', 'BTC')"), + amount: z.number().positive().describe("Amount to transfer"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.subAccountFuturesInternalTransfer({ + fromEmail: params.fromEmail, + toEmail: params.toEmail, + futuresType: params.futuresType, + asset: params.asset, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Futures internal transfer successful!\n\nFrom: ${params.fromEmail}\nTo: ${params.toEmail}\nFutures Type: ${params.futuresType === "1" ? "USD-M" : "COIN-M"}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Futures internal transfer successful!\n\nFrom: ${params.fromEmail}\nTo: ${params.toEmail}\nFutures Type: ${params.futuresType === "1" ? "USD-M" : "COIN-M"}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transfer-api/getTransferHistory.ts b/src/tools/binance-sub-account/transfer-api/getTransferHistory.ts index fcaed7a5..d07f9bd0 100644 --- a/src/tools/binance-sub-account/transfer-api/getTransferHistory.ts +++ b/src/tools/binance-sub-account/transfer-api/getTransferHistory.ts @@ -5,54 +5,59 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/getTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountTransferHistory(server: McpServer) { - server.tool( - "BinanceSubAccountTransferHistory", + server.registerTool( + "BinanceSubAccountTransferHistory", + { + description: "Get transfer history for sub-accounts. Shows all internal transfers between master and sub-accounts.", - { - asset: z.string().optional() - .describe("Filter by specific asset"), - type: z.enum(["1", "2"]).optional() - .describe("Transfer type: 1 = transfer in, 2 = transfer out"), - startTime: z.number().int().optional() - .describe("Start timestamp in ms"), - endTime: z.number().int().optional() - .describe("End timestamp in ms"), - limit: z.number().int().min(1).max(500).optional() - .describe("Number of results (max 500)"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.querySubAccountTransferHistoryV1({ - ...(params.asset && { asset: params.asset }), - ...(params.type && { type: params.type }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + asset: z.string().optional().describe("Filter by specific asset"), + type: z + .enum(["1", "2"]) + .optional() + .describe("Transfer type: 1 = transfer in, 2 = transfer out"), + startTime: z.number().int().optional().describe("Start timestamp in ms"), + endTime: z.number().int().optional().describe("End timestamp in ms"), + limit: z.number().int().min(1).max(500).optional().describe("Number of results (max 500)"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.querySubAccountTransferHistoryV1({ + ...(params.asset && { asset: params.asset }), + ...(params.type && { type: params.type }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Sub-Account Transfer History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `Sub-Account Transfer History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to get transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to get transfer history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transfer-api/index.ts b/src/tools/binance-sub-account/transfer-api/index.ts index 84af79d4..031ffa48 100644 --- a/src/tools/binance-sub-account/transfer-api/index.ts +++ b/src/tools/binance-sub-account/transfer-api/index.ts @@ -5,17 +5,18 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceSubAccountTransferToSub } from "./transferToSubAccount.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceSubAccountFuturesTransfer } from "./futuresTransfer.js"; +import { registerBinanceSubAccountTransferHistory } from "./getTransferHistory.js"; import { registerBinanceSubAccountTransferToMaster } from "./transferToMaster.js"; +import { registerBinanceSubAccountTransferToSub } from "./transferToSubAccount.js"; import { registerBinanceSubAccountUniversalTransfer } from "./universalTransfer.js"; -import { registerBinanceSubAccountTransferHistory } from "./getTransferHistory.js"; -import { registerBinanceSubAccountFuturesTransfer } from "./futuresTransfer.js"; export function registerBinanceSubAccountTransferTools(server: McpServer) { - registerBinanceSubAccountTransferToSub(server); - registerBinanceSubAccountTransferToMaster(server); - registerBinanceSubAccountUniversalTransfer(server); - registerBinanceSubAccountTransferHistory(server); - registerBinanceSubAccountFuturesTransfer(server); + registerBinanceSubAccountTransferToSub(server); + registerBinanceSubAccountTransferToMaster(server); + registerBinanceSubAccountUniversalTransfer(server); + registerBinanceSubAccountTransferHistory(server); + registerBinanceSubAccountFuturesTransfer(server); } diff --git a/src/tools/binance-sub-account/transfer-api/transferToMaster.ts b/src/tools/binance-sub-account/transfer-api/transferToMaster.ts index b78bff11..4e9e6999 100644 --- a/src/tools/binance-sub-account/transfer-api/transferToMaster.ts +++ b/src/tools/binance-sub-account/transfer-api/transferToMaster.ts @@ -5,45 +5,49 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/transferToMaster.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountTransferToMaster(server: McpServer) { - server.tool( - "BinanceSubAccountTransferToMaster", - "Transfer assets from a sub-account back to the master account.", - { - asset: z.string() - .describe("Asset to transfer (e.g., 'BTC', 'USDT')"), - amount: z.number().positive() - .describe("Amount to transfer"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.subAccountTransferSubToMaster({ - asset: params.asset, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + server.registerTool( + "BinanceSubAccountTransferToMaster", + { + description: "Transfer assets from a sub-account back to the master account.", + inputSchema: { + asset: z.string().describe("Asset to transfer (e.g., 'BTC', 'USDT')"), + amount: z.number().positive().describe("Amount to transfer"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.subAccountTransferSubToMaster({ + asset: params.asset, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Transfer to master successful!\n\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Transfer to master successful!\n\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to transfer to master: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to transfer to master: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transfer-api/transferToSubAccount.ts b/src/tools/binance-sub-account/transfer-api/transferToSubAccount.ts index b108e892..a3861a6d 100644 --- a/src/tools/binance-sub-account/transfer-api/transferToSubAccount.ts +++ b/src/tools/binance-sub-account/transfer-api/transferToSubAccount.ts @@ -5,48 +5,52 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/transferToSubAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountTransferToSub(server: McpServer) { - server.tool( - "BinanceSubAccountTransferToSub", + server.registerTool( + "BinanceSubAccountTransferToSub", + { + description: "Transfer assets from one sub-account to another sub-account. Both accounts must belong to the same master account.", - { - toEmail: z.string().email() - .describe("Recipient sub-account email"), - asset: z.string() - .describe("Asset to transfer (e.g., 'BTC', 'USDT')"), - amount: z.number().positive() - .describe("Amount to transfer"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.subAccountTransferSubToSub({ - toEmail: params.toEmail, - asset: params.asset, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + toEmail: z.string().email().describe("Recipient sub-account email"), + asset: z.string().describe("Asset to transfer (e.g., 'BTC', 'USDT')"), + amount: z.number().positive().describe("Amount to transfer"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.subAccountTransferSubToSub({ + toEmail: params.toEmail, + asset: params.asset, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Transfer successful!\n\nTo: ${params.toEmail}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Transfer successful!\n\nTo: ${params.toEmail}\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transfer-api/universalTransfer.ts b/src/tools/binance-sub-account/transfer-api/universalTransfer.ts index 2c9924e3..3c082f16 100644 --- a/src/tools/binance-sub-account/transfer-api/universalTransfer.ts +++ b/src/tools/binance-sub-account/transfer-api/universalTransfer.ts @@ -5,63 +5,74 @@ * @license Apache-2.0 */ // src/tools/binance-sub-account/transfer-api/universalTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { spotClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { spotClient } from "../../../config/binanceClient.js"; + export function registerBinanceSubAccountUniversalTransfer(server: McpServer) { - server.tool( - "BinanceSubAccountUniversalTransfer", + server.registerTool( + "BinanceSubAccountUniversalTransfer", + { + description: "Universal transfer between master account and sub-accounts, supporting various account types (spot, margin, futures, etc.).", - { - fromEmail: z.string().email().optional() - .describe("Sender email (leave empty for master account)"), - toEmail: z.string().email().optional() - .describe("Recipient email (leave empty for master account)"), - fromAccountType: z.enum(["SPOT", "USDT_FUTURE", "COIN_FUTURE", "MARGIN", "ISOLATED_MARGIN"]) - .describe("Source account type"), - toAccountType: z.enum(["SPOT", "USDT_FUTURE", "COIN_FUTURE", "MARGIN", "ISOLATED_MARGIN"]) - .describe("Destination account type"), - clientTranId: z.string().optional() - .describe("Client transfer ID for idempotency"), - symbol: z.string().optional() - .describe("Required for isolated margin transfers"), - asset: z.string() - .describe("Asset to transfer (e.g., 'BTC', 'USDT')"), - amount: z.number().positive() - .describe("Amount to transfer"), - recvWindow: z.number().int().optional() - .describe("Time window for request validity in ms") - }, - async (params) => { - try { - const response = await spotClient.restAPI.universalTransfer({ - fromAccountType: params.fromAccountType, - toAccountType: params.toAccountType, - asset: params.asset, - amount: params.amount, - ...(params.fromEmail && { fromEmail: params.fromEmail }), - ...(params.toEmail && { toEmail: params.toEmail }), - ...(params.clientTranId && { clientTranId: params.clientTranId }), - ...(params.symbol && { symbol: params.symbol }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + fromEmail: z + .string() + .email() + .optional() + .describe("Sender email (leave empty for master account)"), + toEmail: z + .string() + .email() + .optional() + .describe("Recipient email (leave empty for master account)"), + fromAccountType: z + .enum(["SPOT", "USDT_FUTURE", "COIN_FUTURE", "MARGIN", "ISOLATED_MARGIN"]) + .describe("Source account type"), + toAccountType: z + .enum(["SPOT", "USDT_FUTURE", "COIN_FUTURE", "MARGIN", "ISOLATED_MARGIN"]) + .describe("Destination account type"), + clientTranId: z.string().optional().describe("Client transfer ID for idempotency"), + symbol: z.string().optional().describe("Required for isolated margin transfers"), + asset: z.string().describe("Asset to transfer (e.g., 'BTC', 'USDT')"), + amount: z.number().positive().describe("Amount to transfer"), + recvWindow: z.number().int().optional().describe("Time window for request validity in ms"), + }, + }, + async (params) => { + try { + const response = await (spotClient as any).restAPI.universalTransfer({ + fromAccountType: params.fromAccountType, + toAccountType: params.toAccountType, + asset: params.asset, + amount: params.amount, + ...(params.fromEmail && { fromEmail: params.fromEmail }), + ...(params.toEmail && { toEmail: params.toEmail }), + ...(params.clientTranId && { clientTranId: params.clientTranId }), + ...(params.symbol && { symbol: params.symbol }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `✅ Universal transfer successful!\n\nFrom: ${params.fromEmail || "Master"} (${params.fromAccountType})\nTo: ${params.toEmail || "Master"} (${params.toAccountType})\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ - type: "text", - text: `✅ Universal transfer successful!\n\nFrom: ${params.fromEmail || 'Master'} (${params.fromAccountType})\nTo: ${params.toEmail || 'Master'} (${params.toAccountType})\nAsset: ${params.asset}\nAmount: ${params.amount}\n\nTransaction: ${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `❌ Failed to transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transferToMaster.ts b/src/tools/binance-sub-account/transferToMaster.ts index ea2304c0..20c3ab8e 100644 --- a/src/tools/binance-sub-account/transferToMaster.ts +++ b/src/tools/binance-sub-account/transferToMaster.ts @@ -1,41 +1,47 @@ // src/tools/binance-sub-account/transferToMaster.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountTransferToMaster(server: McpServer) { - server.tool( - "BinanceSubAccountTransferToMaster", + server.registerTool( + "BinanceSubAccountTransferToMaster", + { + description: "Transfer assets from sub-account to master account (SPOT). Must be called from sub-account API key.", - { - asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), - amount: z.number().describe("Amount to transfer"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, amount, recvWindow }) => { - try { - const params: any = { asset, amount }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.transferToMaster(params); + inputSchema: { + asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), + amount: z.number().describe("Amount to transfer"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, amount, recvWindow }) => { + try { + const params: any = { asset, amount }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.transferToMaster(params); + + return { + content: [ + { + type: "text", + text: `Transferred ${amount} ${asset} to master account. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Transferred ${amount} ${asset} to master account. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to transfer to master account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to transfer to master account: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/transferToSubAccount.ts b/src/tools/binance-sub-account/transferToSubAccount.ts index 5109ea81..863fa984 100644 --- a/src/tools/binance-sub-account/transferToSubAccount.ts +++ b/src/tools/binance-sub-account/transferToSubAccount.ts @@ -1,42 +1,45 @@ // src/tools/binance-sub-account/transferToSubAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountTransferToSub(server: McpServer) { - server.tool( - "BinanceSubAccountTransferToSub", - "Transfer assets from master account to sub-account (SPOT).", - { - toEmail: z.string().describe("Sub-account email to transfer to"), - asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), - amount: z.number().describe("Amount to transfer"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ toEmail, asset, amount, recvWindow }) => { - try { - const params: any = { toEmail, asset, amount }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.transferToSubAccount(params); + server.registerTool( + "BinanceSubAccountTransferToSub", + { + description: "Transfer assets from master account to sub-account (SPOT).", + inputSchema: { + toEmail: z.string().describe("Sub-account email to transfer to"), + asset: z.string().describe("Asset to transfer (e.g., BTC, USDT)"), + amount: z.number().describe("Amount to transfer"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ toEmail, asset, amount, recvWindow }) => { + try { + const params: any = { toEmail, asset, amount }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.transferToSubAccount(params); + + return { + content: [ + { + type: "text", + text: `Transferred ${amount} ${asset} to ${toEmail}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Transferred ${amount} ${asset} to ${toEmail}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to transfer to sub-account: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to transfer to sub-account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/universalTransfer.ts b/src/tools/binance-sub-account/universalTransfer.ts index 358fce2b..c3aff19b 100644 --- a/src/tools/binance-sub-account/universalTransfer.ts +++ b/src/tools/binance-sub-account/universalTransfer.ts @@ -1,49 +1,72 @@ // src/tools/binance-sub-account/universalTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountUniversalTransfer(server: McpServer) { - server.tool( - "BinanceSubAccountUniversalTransfer", - "Universal transfer between sub-accounts or between master and sub-accounts.", - { - fromEmail: z.string().optional().describe("Sender email (leave empty for master account)"), - toEmail: z.string().optional().describe("Recipient email (leave empty for master account)"), - fromAccountType: z.string().describe("Sender account type: SPOT, USDT_FUTURE, COIN_FUTURE, MARGIN, ISOLATED_MARGIN"), - toAccountType: z.string().describe("Recipient account type: SPOT, USDT_FUTURE, COIN_FUTURE, MARGIN, ISOLATED_MARGIN"), - asset: z.string().describe("Asset to transfer"), - amount: z.number().describe("Amount to transfer"), - symbol: z.string().optional().describe("Required when fromAccountType or toAccountType is ISOLATED_MARGIN"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ fromEmail, toEmail, fromAccountType, toAccountType, asset, amount, symbol, recvWindow }) => { - try { - const params: any = { fromAccountType, toAccountType, asset, amount }; - if (fromEmail !== undefined) params.fromEmail = fromEmail; - if (toEmail !== undefined) params.toEmail = toEmail; - if (symbol !== undefined) params.symbol = symbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.subAccountUniversalTransfer(params); + server.registerTool( + "BinanceSubAccountUniversalTransfer", + { + description: "Universal transfer between sub-accounts or between master and sub-accounts.", + inputSchema: { + fromEmail: z.string().optional().describe("Sender email (leave empty for master account)"), + toEmail: z.string().optional().describe("Recipient email (leave empty for master account)"), + fromAccountType: z + .string() + .describe("Sender account type: SPOT, USDT_FUTURE, COIN_FUTURE, MARGIN, ISOLATED_MARGIN"), + toAccountType: z + .string() + .describe( + "Recipient account type: SPOT, USDT_FUTURE, COIN_FUTURE, MARGIN, ISOLATED_MARGIN", + ), + asset: z.string().describe("Asset to transfer"), + amount: z.number().describe("Amount to transfer"), + symbol: z + .string() + .optional() + .describe("Required when fromAccountType or toAccountType is ISOLATED_MARGIN"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + fromEmail, + toEmail, + fromAccountType, + toAccountType, + asset, + amount, + symbol, + recvWindow, + }) => { + try { + const params: any = { fromAccountType, toAccountType, asset, amount }; + if (fromEmail !== undefined) params.fromEmail = fromEmail; + if (toEmail !== undefined) params.toEmail = toEmail; + if (symbol !== undefined) params.symbol = symbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.subAccountUniversalTransfer(params); + + return { + content: [ + { + type: "text", + text: `Universal transfer completed: ${amount} ${asset}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Universal transfer completed: ${amount} ${asset}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to execute universal transfer: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [ + { type: "text", text: `Failed to execute universal transfer: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-sub-account/updateIpRestriction.ts b/src/tools/binance-sub-account/updateIpRestriction.ts index a3b73be1..227fc350 100644 --- a/src/tools/binance-sub-account/updateIpRestriction.ts +++ b/src/tools/binance-sub-account/updateIpRestriction.ts @@ -1,44 +1,47 @@ // src/tools/binance-sub-account/updateIpRestriction.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { subAccountApiClient } from "../../config/binanceClient.js"; export function registerBinanceSubAccountUpdateIpRestriction(server: McpServer) { - server.tool( - "BinanceSubAccountUpdateIpRestriction", - "Update IP restriction for a sub-account API key.", - { - subAccountId: z.string().describe("Sub-account ID"), - subAccountApiKey: z.string().describe("Sub-account API key"), - status: z.string().describe("IP restriction status: 1 - Restrict by IP, 2 - Unrestrict"), - ipAddress: z.string().optional().describe("IP address (comma-separated for multiple)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, subAccountApiKey, status, ipAddress, recvWindow }) => { - try { - const params: any = { subAccountId, subAccountApiKey, status }; - if (ipAddress !== undefined) params.ipAddress = ipAddress; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await subAccountApiClient.updateSubAccountApiKeyIpRestriction(params); + server.registerTool( + "BinanceSubAccountUpdateIpRestriction", + { + description: "Update IP restriction for a sub-account API key.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + subAccountApiKey: z.string().describe("Sub-account API key"), + status: z.string().describe("IP restriction status: 1 - Restrict by IP, 2 - Unrestrict"), + ipAddress: z.string().optional().describe("IP address (comma-separated for multiple)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, subAccountApiKey, status, ipAddress, recvWindow }) => { + try { + const params: any = { subAccountId, subAccountApiKey, status }; + if (ipAddress !== undefined) params.ipAddress = ipAddress; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await subAccountApiClient.updateSubAccountApiKeyIpRestriction(params); + + return { + content: [ + { + type: "text", + text: `IP restriction updated for sub-account API key. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `IP restriction updated for sub-account API key. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to update IP restriction: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to update IP restriction: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/index.ts b/src/tools/binance-vip-loan/index.ts index a94ffa9e..8afb223a 100644 --- a/src/tools/binance-vip-loan/index.ts +++ b/src/tools/binance-vip-loan/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceVipLoanMarketApiTools } from "./market-api/index.js"; import { registerBinanceVipLoanTradeApiTools } from "./trade-api/index.js"; import { registerBinanceVipLoanUserInformationApiTools } from "./userInformation-api/index.js"; export function registerBinanceVipLoanTools(server: McpServer) { - registerBinanceVipLoanMarketApiTools(server); - registerBinanceVipLoanTradeApiTools(server); - registerBinanceVipLoanUserInformationApiTools(server); + registerBinanceVipLoanMarketApiTools(server); + registerBinanceVipLoanTradeApiTools(server); + registerBinanceVipLoanUserInformationApiTools(server); } diff --git a/src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts b/src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts index 51888e73..44d6f45d 100644 --- a/src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts +++ b/src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/market-api/getBorrowInterestRate.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetBorrowInterestRate(server: McpServer) { - server.tool( - "BinanceGetBorrowInterestRate", + server.registerTool( + "BinanceGetBorrowInterestRate", + { + description: "Retrieves the interest rates for borrowing assets. It provides both daily and yearly interest rates for multiple assets (e.g., BUSD, BTC). You can specify the assets by using a comma-separated list.", - { - loanCoin: z.string().min(1).describe("Max 10 assets, multiple split by ','"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getBorrowInterestRate({ - loanCoin: params.loanCoin, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().min(1).describe("Max 10 assets, multiple split by ','"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getBorrowInterestRate({ + loanCoin: params.loanCoin, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved the interest rates for borrowing assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved the interest rates for borrowing assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve the interest rates for borrowing assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve the interest rates for borrowing assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts b/src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts index 5f9c7a34..2c87c84c 100644 --- a/src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts +++ b/src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/market-api/getCollateralAssetData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetCollateralAssetData(server: McpServer) { - server.tool( - "BinanceGetCollateralAssetData", + server.registerTool( + "BinanceGetCollateralAssetData", + { + description: "Retrieves information about collateral assets, including collateral ratios and range values for different tiers of collateral. The ratios are used to determine the collateral requirement for various levels of borrowing.", - { - collateralCoin: z.string().optional().describe("Optional: Coin used as collateral"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getCollateralAssetData({ - ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + collateralCoin: z.string().optional().describe("Optional: Coin used as collateral"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getCollateralAssetData({ + ...(params.collateralCoin && { collateralCoin: params.collateralCoin }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved information about collateral assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved information about collateral assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve information about collateral assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve information about collateral assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts b/src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts index 5c256508..8c448656 100644 --- a/src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts +++ b/src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts @@ -1,49 +1,63 @@ // src/tools/binance-vip-loan/market-api/getLoanableAssetsData.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetLoanableAssetsData(server: McpServer) { - server.tool( - "BinanceGetLoanableAssetsData", + server.registerTool( + "BinanceGetLoanableAssetsData", + { + description: "Retrieves interest rates and borrowing limits for loanable assets. The borrow limit is expressed in USD. You can request information for specific assets or leave it empty to query all available assets.", - { - loanCoin: z.string().optional().describe("Optional: Coin for the loan"), - vipLevel: z.number().int().optional().describe("Optional: User's VIP level (default is user's vip level)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getLoanableAssetsData({ - ...(params.loanCoin && { loanCoin: params.loanCoin }), - ...(params.vipLevel && { vipLevel: params.vipLevel }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanCoin: z.string().optional().describe("Optional: Coin for the loan"), + vipLevel: z + .number() + .int() + .optional() + .describe("Optional: User's VIP level (default is user's vip level)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getLoanableAssetsData({ + ...(params.loanCoin && { loanCoin: params.loanCoin }), + ...(params.vipLevel && { vipLevel: params.vipLevel }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved interest rates and borrowing limits for loanable assets. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved interest rates and borrowing limits for loanable assets. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve interest rates and borrowing limits for loanable assets. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve interest rates and borrowing limits for loanable assets. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/market-api/index.ts b/src/tools/binance-vip-loan/market-api/index.ts index 3e0ee81a..5ee3c97f 100644 --- a/src/tools/binance-vip-loan/market-api/index.ts +++ b/src/tools/binance-vip-loan/market-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/market-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceGetBorrowInterestRate } from "./getBorrowInterestRate.js"; -import { registerBinanceGetLoanableAssetsData } from "./getLoanableAssetsData.js"; import { registerBinanceGetCollateralAssetData } from "./getCollateralAssetData.js"; +import { registerBinanceGetLoanableAssetsData } from "./getLoanableAssetsData.js"; export function registerBinanceVipLoanMarketApiTools(server: McpServer) { - registerBinanceGetBorrowInterestRate(server); - registerBinanceGetCollateralAssetData(server); - registerBinanceGetLoanableAssetsData(server); + registerBinanceGetBorrowInterestRate(server); + registerBinanceGetCollateralAssetData(server); + registerBinanceGetLoanableAssetsData(server); } diff --git a/src/tools/binance-vip-loan/trade-api/index.ts b/src/tools/binance-vip-loan/trade-api/index.ts index 7395b3ff..95c9cb6c 100644 --- a/src/tools/binance-vip-loan/trade-api/index.ts +++ b/src/tools/binance-vip-loan/trade-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/trade-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceVipLoanBorrow } from "./vipLoanBorrow.js"; import { registerBinanceVipLoanRenew } from "./vipLoanRenew.js"; import { registerBinanceVipLoanRepay } from "./vipLoanRepay.js"; -import { registerBinanceVipLoanBorrow } from "./vipLoanBorrow.js"; export function registerBinanceVipLoanTradeApiTools(server: McpServer) { - registerBinanceVipLoanRenew(server); - registerBinanceVipLoanRepay(server); - registerBinanceVipLoanBorrow(server); + registerBinanceVipLoanRenew(server); + registerBinanceVipLoanRepay(server); + registerBinanceVipLoanBorrow(server); } diff --git a/src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts b/src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts index 2dc82b5f..e69a71e2 100644 --- a/src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts +++ b/src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts @@ -1,59 +1,78 @@ // src/tools/binance-vip-loan/trade-api/vipLoanBorrow.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanBorrow(server: McpServer) { - server.tool( - "BinanceVipLoanBorrow", + server.registerTool( + "BinanceVipLoanBorrow", + { + description: "Allow users (master account only) to apply for a loan by pledging collateral. Users specify the coin they want to borrow, the amount, and the collateral details.", - { - loanAccountId: z.number().int().describe("Loan account ID"), - loanCoin: z.string().min(1).describe("Loan coin (e.g., BTC, ETH)"), - loanAmount: z.number().describe("Loan amount as decimal"), - collateralAccountId: z.string().min(1).describe("Collateral account IDs, separated by commas"), - collateralCoin: z.string().min(1).describe("Collateral coins, separated by commas"), - isFlexibleRate: z.boolean().describe("TRUE: flexible rate, FALSE: fixed rate. Default: TRUE"), - loanTerm: z.number().int().optional().describe("Loan term (only required if fixed rate, e.g., 30/60 days)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanBorrow({ - loanAccountId: params.loanAccountId, - loanCoin: params.loanCoin, - loanAmount: params.loanAmount, - collateralAccountId: params.collateralAccountId, - collateralCoin: params.collateralCoin, - isFlexibleRate: params.isFlexibleRate, - ...(params.loanTerm !== undefined && { loanTerm: params.loanTerm }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + loanAccountId: z.number().int().describe("Loan account ID"), + loanCoin: z.string().min(1).describe("Loan coin (e.g., BTC, ETH)"), + loanAmount: z.number().describe("Loan amount as decimal"), + collateralAccountId: z + .string() + .min(1) + .describe("Collateral account IDs, separated by commas"), + collateralCoin: z.string().min(1).describe("Collateral coins, separated by commas"), + isFlexibleRate: z + .boolean() + .describe("TRUE: flexible rate, FALSE: fixed rate. Default: TRUE"), + loanTerm: z + .number() + .int() + .optional() + .describe("Loan term (only required if fixed rate, e.g., 30/60 days)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanBorrow({ + loanAccountId: params.loanAccountId, + loanCoin: params.loanCoin, + loanAmount: params.loanAmount, + collateralAccountId: params.collateralAccountId, + collateralCoin: params.collateralCoin, + isFlexibleRate: params.isFlexibleRate, + ...(params.loanTerm !== undefined && { loanTerm: params.loanTerm }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully apply for a loan by pledging collateral. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully apply for a loan by pledging collateral. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to apply for a loan by pledging collateral. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to apply for a loan by pledging collateral. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts b/src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts index 50e7491c..a05a1d43 100644 --- a/src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts +++ b/src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts @@ -1,46 +1,58 @@ // src/tools/binance-vip-loan/trade-api/vipLoanRenew.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanRenew(server: McpServer) { - server.tool( - "BinanceVipLoanRenew", + server.registerTool( + "BinanceVipLoanRenew", + { + description: "Allow VIP users to renew an existing VIP loan for a specified term, either 30 or 60 days.", - { - orderId: z.number().int().describe("The order ID for the loan request"), - loanTerm: z.union([z.literal(30), z.literal(60)]).describe("Loan term in days, either 30 or 60"), - recvWindow: z.number().int().optional().describe("Optional: Time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanRenew({ - orderId: params.orderId, - loanTerm: params.loanTerm, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - const data = await response.data(); + inputSchema: { + orderId: z.number().int().describe("The order ID for the loan request"), + loanTerm: z + .union([z.literal(30), z.literal(60)]) + .describe("Loan term in days, either 30 or 60"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional: Time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanRenew({ + orderId: params.orderId, + loanTerm: params.loanTerm, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Successfully renew an existing VIP loan. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully renew an existing VIP loan. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to renew an existing VIP loan. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to renew an existing VIP loan. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts b/src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts index e6389ef0..3b8c2e71 100644 --- a/src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts +++ b/src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts @@ -1,47 +1,57 @@ // src/tools/binance-vip-loan/trade-api/vipLoanRepay.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceVipLoanRepay(server: McpServer) { - server.tool( - "BinanceVipLoanRepay", + server.registerTool( + "BinanceVipLoanRepay", + { + description: "Allow VIP users to repay a specified amount of their active loan, partially or fully. It updates the remaining principal and interest, and provides the repayment status.", - { - orderId: z.number().int().describe("Order ID of the loan request"), - amount: z.number().describe("Amount to be processed (decimal allowed)"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.vipLoanRepay({ - orderId: params.orderId, - amount: params.amount, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().describe("Order ID of the loan request"), + amount: z.number().describe("Amount to be processed (decimal allowed)"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.vipLoanRepay({ + orderId: params.orderId, + amount: params.amount, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully repay the active loan. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully repay the active loan. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to repay the active loan. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to repay the active loan. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts b/src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts index 841d583e..c7cea037 100644 --- a/src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts +++ b/src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts @@ -1,51 +1,61 @@ // src/tools/binance-vip-loan/userInformation-api/checkVIPLoanCollateralAccount.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceCheckVIPLoanCollateralAccount(server: McpServer) { - server.tool( - "BinanceCheckVIPLoanCollateralAccount", + server.registerTool( + "BinanceCheckVIPLoanCollateralAccount", + { + description: "Allow users to check their collateral accounts and the coins held as collateral. If the logged-in account is a loan account, it will return all associated collateral accounts. If it's a collateral account, it returns details of the current account only.", - { - orderId: z.number().int().optional().describe("Optional order ID"), - collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.checkVIPLoanCollateralAccount({ - ...(params.orderId !== undefined && { orderId: params.orderId }), - ...(params.collateralAccountId !== undefined && { - collateralAccountId: params.collateralAccountId - }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().optional().describe("Optional order ID"), + collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.checkVIPLoanCollateralAccount({ + ...(params.orderId !== undefined && { orderId: params.orderId }), + ...(params.collateralAccountId !== undefined && { + collateralAccountId: params.collateralAccountId, + }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved collateral accounts and the coins held as collateral. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved collateral accounts and the coins held as collateral. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve collateral accounts and the coins held as collateral. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve collateral accounts and the coins held as collateral. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts b/src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts index 70c69c6f..f1edc4b2 100644 --- a/src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts +++ b/src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts @@ -1,59 +1,81 @@ // src/tools/binance-vip-loan/userInformation-api/getVIPLoanOngoingOrders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceGetVIPLoanOngoingOrders(server: McpServer) { - server.tool( - "BinanceGetVIPLoanOngoingOrders", + server.registerTool( + "BinanceGetVIPLoanOngoingOrders", + { + description: "Allows VIP users to retrieve a list of their current active loan orders. Users can filter results by loan coin, collateral coin, order ID, or collateral account ID.", - { - orderId: z.number().int().optional().describe("Optional order ID"), - collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), - loanCoin: z.string().optional().describe("Optional loan coin"), - collateralCoin: z.string().optional().describe("Optional collateral coin"), - current: z.number().int().min(1).max(1000).optional().describe("Current page, start from 1, max 1000"), - limit: z.number().int().min(1).max(100).optional().describe("Results per page, default 10, max 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.getVIPLoanOngoingOrders({ - ...(params.orderId !== undefined && { orderId: params.orderId }), - ...(params.collateralAccountId !== undefined && { - collateralAccountId: params.collateralAccountId - }), - ...(params.loanCoin !== undefined && { loanCoin: params.loanCoin }), - ...(params.collateralCoin !== undefined && { collateralCoin: params.collateralCoin }), - ...(params.current !== undefined && { current: params.current }), - ...(params.limit !== undefined && { limit: params.limit }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + orderId: z.number().int().optional().describe("Optional order ID"), + collateralAccountId: z.number().int().optional().describe("Optional collateral account ID"), + loanCoin: z.string().optional().describe("Optional loan coin"), + collateralCoin: z.string().optional().describe("Optional collateral coin"), + current: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Current page, start from 1, max 1000"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Results per page, default 10, max 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.getVIPLoanOngoingOrders({ + ...(params.orderId !== undefined && { orderId: params.orderId }), + ...(params.collateralAccountId !== undefined && { + collateralAccountId: params.collateralAccountId, + }), + ...(params.loanCoin !== undefined && { loanCoin: params.loanCoin }), + ...(params.collateralCoin !== undefined && { collateralCoin: params.collateralCoin }), + ...(params.current !== undefined && { current: params.current }), + ...(params.limit !== undefined && { limit: params.limit }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved list of their current active loan orders. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved list of their current active loan orders. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve list of their current active loan orders. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve list of their current active loan orders. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-vip-loan/userInformation-api/index.ts b/src/tools/binance-vip-loan/userInformation-api/index.ts index 58bad6e4..fcffe103 100644 --- a/src/tools/binance-vip-loan/userInformation-api/index.ts +++ b/src/tools/binance-vip-loan/userInformation-api/index.ts @@ -1,11 +1,12 @@ // src/tools/binance-vip-loan/userInformation-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceCheckVIPLoanCollateralAccount } from "./checkVIPLoanCollateralAccount.js"; import { registerBinanceGetVIPLoanOngoingOrders } from "./getVIPLoanOngoingOrders.js"; import { registerBinanceQueryApplicationStatus } from "./queryApplicationStatus.js"; export function registerBinanceVipLoanUserInformationApiTools(server: McpServer) { - registerBinanceCheckVIPLoanCollateralAccount(server); - registerBinanceGetVIPLoanOngoingOrders(server); - registerBinanceQueryApplicationStatus(server); + registerBinanceCheckVIPLoanCollateralAccount(server); + registerBinanceGetVIPLoanOngoingOrders(server); + registerBinanceQueryApplicationStatus(server); } diff --git a/src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts b/src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts index 7d5e5a05..8d7d1b96 100644 --- a/src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts +++ b/src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts @@ -1,55 +1,65 @@ // src/tools/binance-vip-loan/userInformation-api/queryApplicationStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { vipLoanClient } from "../../../config/binanceClient.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; +import { vipLoanClient } from "../../../config/binanceClient.js"; + export function registerBinanceQueryApplicationStatus(server: McpServer) { - server.tool( - "BinanceQueryApplicationStatus", + server.registerTool( + "BinanceQueryApplicationStatus", + { + description: "Allows VIP users to check the status of their loan applications. It returns a list of loan requests with details such as loan coin, amount, term, collateral details, and current application status", - { - current: z - .number() - .int() - .min(1) - .max(1000) - .optional() - .describe("Currently querying page. Start from 1, default 1, max 1000"), - limit: z.number().int().min(1).max(100).optional().describe("Default: 10, Max: 100"), - recvWindow: z.number().int().optional().describe("Optional time window for request validity") - }, - async (params) => { - try { - const response = await vipLoanClient.restAPI.queryApplicationStatus({ - ...(params.current !== undefined && { current: params.current }), - ...(params.limit !== undefined && { limit: params.limit }), - ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }) - }); + inputSchema: { + current: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .describe("Currently querying page. Start from 1, default 1, max 1000"), + limit: z.number().int().min(1).max(100).optional().describe("Default: 10, Max: 100"), + recvWindow: z + .number() + .int() + .optional() + .describe("Optional time window for request validity"), + }, + }, + async (params) => { + try { + const response = await vipLoanClient.restAPI.queryApplicationStatus({ + ...(params.current !== undefined && { current: params.current }), + ...(params.limit !== undefined && { limit: params.limit }), + ...(params.recvWindow !== undefined && { recvWindow: params.recvWindow }), + }); + + const data = await response.data(); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Successfully retrieved status of their loan applications. Response: ${JSON.stringify( + data, + )}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Successfully retrieved status of their loan applications. Response: ${JSON.stringify( - data - )}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Failed to retrieve status of their loan applications.. ${errorMessage}` - } - ], - isError: true - }; - } - } - ); + return { + content: [ + { + type: "text", + text: `Failed to retrieve status of their loan applications.. ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/binance-wallet/account-api/accountApiTradingStatus.ts b/src/tools/binance-wallet/account-api/accountApiTradingStatus.ts index d5ed7e7b..99e08066 100644 --- a/src/tools/binance-wallet/account-api/accountApiTradingStatus.ts +++ b/src/tools/binance-wallet/account-api/accountApiTradingStatus.ts @@ -1,40 +1,48 @@ // src/tools/binance-wallet/account-api/accountApiTradingStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountApiTradingStatus(server: McpServer) { - server.tool( - "BinanceWalletAccountApiTradingStatus", - "Get account API trading status.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountApiTradingStatus(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountApiTradingStatus", + { + description: "Get account API trading status.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountApiTradingStatus(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved account API trading status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved account API trading status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve account API trading status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve account API trading status: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/accountInfo.ts b/src/tools/binance-wallet/account-api/accountInfo.ts index 4b426dc4..74e27c16 100644 --- a/src/tools/binance-wallet/account-api/accountInfo.ts +++ b/src/tools/binance-wallet/account-api/accountInfo.ts @@ -1,40 +1,48 @@ // src/tools/binance-wallet/account-api/accountInfo.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountInfo(server: McpServer) { - server.tool( - "BinanceWalletAccountInfo", - "Get Binance Wallet account information.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountInfo(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountInfo", + { + description: "Get Binance Wallet account information.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountInfo(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved wallet account information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved wallet account information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve wallet account information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve wallet account information: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/accountStatus.ts b/src/tools/binance-wallet/account-api/accountStatus.ts index e5efdcec..e76fb3b2 100644 --- a/src/tools/binance-wallet/account-api/accountStatus.ts +++ b/src/tools/binance-wallet/account-api/accountStatus.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/accountStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAccountStatus(server: McpServer) { - server.tool( - "BinanceWalletAccountStatus", - "Get Binance Wallet account status.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.accountStatus(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAccountStatus", + { + description: "Get Binance Wallet account status.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.accountStatus(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved wallet account status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved wallet account status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve wallet account status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve wallet account status: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts b/src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts index 8bfde6f8..388a6906 100644 --- a/src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts +++ b/src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts @@ -1,47 +1,52 @@ // src/tools/binance-wallet/account-api/dailyAccountSnapshot.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDailyAccountSnapshot(server: McpServer) { - server.tool( - "BinanceWalletDailyAccountSnapshot", - "Get daily account snapshot.", - { - type: z.string().describe("The account type (e.g., SPOT, MARGIN, FUTURES)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 7, max 30"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, startTime, endTime, limit, recvWindow }) => { - try { - const params: any = { type }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dailyAccountSnapshot(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDailyAccountSnapshot", + { + description: "Get daily account snapshot.", + inputSchema: { + type: z.string().describe("The account type (e.g., SPOT, MARGIN, FUTURES)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 7, max 30"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, startTime, endTime, limit, recvWindow }) => { + try { + const params: any = { type }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dailyAccountSnapshot(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved daily account snapshot for ${type}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved daily account snapshot for ${type}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve daily account snapshot: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve daily account snapshot: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts b/src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts index 5e0e8106..46b33792 100644 --- a/src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts +++ b/src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/disableFastWithdrawSwitch.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDisableFastWithdrawSwitch(server: McpServer) { - server.tool( - "BinanceWalletDisableFastWithdrawSwitch", - "Disable fast withdraw switch.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.disableFastWithdrawSwitch(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDisableFastWithdrawSwitch", + { + description: "Disable fast withdraw switch.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.disableFastWithdrawSwitch(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Disabled fast withdraw switch. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Disabled fast withdraw switch. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to disable fast withdraw switch: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to disable fast withdraw switch: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts b/src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts index d6679332..b4d54e4b 100644 --- a/src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts +++ b/src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/enableFastWithdrawSwitch.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletEnableFastWithdrawSwitch(server: McpServer) { - server.tool( - "BinanceWalletEnableFastWithdrawSwitch", - "Enable fast withdraw switch.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.enableFastWithdrawSwitch(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletEnableFastWithdrawSwitch", + { + description: "Enable fast withdraw switch.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.enableFastWithdrawSwitch(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Enabled fast withdraw switch. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Enabled fast withdraw switch. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to enable fast withdraw switch: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to enable fast withdraw switch: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/getApiKeyPermission.ts b/src/tools/binance-wallet/account-api/getApiKeyPermission.ts index 773e8175..cab47335 100644 --- a/src/tools/binance-wallet/account-api/getApiKeyPermission.ts +++ b/src/tools/binance-wallet/account-api/getApiKeyPermission.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/account-api/getApiKeyPermission.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetApiKeyPermission(server: McpServer) { - server.tool( - "BinanceWalletGetApiKeyPermission", - "Get API key permission.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getApiKeyPermission(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetApiKeyPermission", + { + description: "Get API key permission.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getApiKeyPermission(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved API key permission. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved API key permission. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve API key permission: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve API key permission: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/account-api/index.ts b/src/tools/binance-wallet/account-api/index.ts index 0b8cfdf0..d454e39c 100644 --- a/src/tools/binance-wallet/account-api/index.ts +++ b/src/tools/binance-wallet/account-api/index.ts @@ -1,20 +1,20 @@ // src/tools/binance-wallet/account-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletDailyAccountSnapshot } from "./dailyAccountSnapshot.js"; -import { registerBinanceWalletGetApiKeyPermission } from "./getApiKeyPermission.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { registerBinanceWalletAccountApiTradingStatus } from "./accountApiTradingStatus.js"; import { registerBinanceWalletAccountInfo } from "./accountInfo.js"; import { registerBinanceWalletAccountStatus } from "./accountStatus.js"; -import { registerBinanceWalletAccountApiTradingStatus } from "./accountApiTradingStatus.js"; -import { registerBinanceWalletEnableFastWithdrawSwitch } from "./enableFastWithdrawSwitch.js"; +import { registerBinanceWalletDailyAccountSnapshot } from "./dailyAccountSnapshot.js"; import { registerBinanceWalletDisableFastWithdrawSwitch } from "./disableFastWithdrawSwitch.js"; +import { registerBinanceWalletEnableFastWithdrawSwitch } from "./enableFastWithdrawSwitch.js"; +import { registerBinanceWalletGetApiKeyPermission } from "./getApiKeyPermission.js"; export function registerBinanceWalletAccountApiTools(server: McpServer) { - registerBinanceWalletDailyAccountSnapshot(server); - registerBinanceWalletGetApiKeyPermission(server); - registerBinanceWalletAccountInfo(server); - registerBinanceWalletAccountStatus(server); - registerBinanceWalletAccountApiTradingStatus(server); - registerBinanceWalletEnableFastWithdrawSwitch(server); - registerBinanceWalletDisableFastWithdrawSwitch(server); - -} \ No newline at end of file + registerBinanceWalletDailyAccountSnapshot(server); + registerBinanceWalletGetApiKeyPermission(server); + registerBinanceWalletAccountInfo(server); + registerBinanceWalletAccountStatus(server); + registerBinanceWalletAccountApiTradingStatus(server); + registerBinanceWalletEnableFastWithdrawSwitch(server); + registerBinanceWalletDisableFastWithdrawSwitch(server); +} diff --git a/src/tools/binance-wallet/asset-api/assetDetail.ts b/src/tools/binance-wallet/asset-api/assetDetail.ts index 8eabf38b..c4f5a55b 100644 --- a/src/tools/binance-wallet/asset-api/assetDetail.ts +++ b/src/tools/binance-wallet/asset-api/assetDetail.ts @@ -1,42 +1,45 @@ // src/tools/binance-wallet/asset-api/assetDetail.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAssetDetail(server: McpServer) { - server.tool( - "BinanceWalletAssetDetail", - "Get asset details.", - { - asset: z.string().optional().describe("Asset symbol"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.assetDetail(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAssetDetail", + { + description: "Get asset details.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.assetDetail(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved asset details. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset details. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset details: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve asset details: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/assetDividendRecord.ts b/src/tools/binance-wallet/asset-api/assetDividendRecord.ts index c24cff7d..29dbba85 100644 --- a/src/tools/binance-wallet/asset-api/assetDividendRecord.ts +++ b/src/tools/binance-wallet/asset-api/assetDividendRecord.ts @@ -1,48 +1,53 @@ // src/tools/binance-wallet/asset-api/assetDividendRecord.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAssetDividendRecord(server: McpServer) { - server.tool( - "BinanceWalletAssetDividendRecord", - "Get asset dividend record.", - { - asset: z.string().optional().describe("Asset symbol"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Default 20, max 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, startTime, endTime, limit, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.assetDividendRecord(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAssetDividendRecord", + { + description: "Get asset dividend record.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Default 20, max 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, startTime, endTime, limit, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.assetDividendRecord(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved asset dividend record. Total records: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved asset dividend record. Total records: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve asset dividend record: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve asset dividend record: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/dustTransfer.ts b/src/tools/binance-wallet/asset-api/dustTransfer.ts index 74d7b520..0be0bdb5 100644 --- a/src/tools/binance-wallet/asset-api/dustTransfer.ts +++ b/src/tools/binance-wallet/asset-api/dustTransfer.ts @@ -1,42 +1,44 @@ - // src/tools/binance-wallet/asset-api/dustTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDustTransfer(server: McpServer) { - server.tool( - "BinanceWalletDustTransfer", - "Convert dust assets to BNB.", - { - asset: z.array(z.string()).describe("Array of asset symbols to convert"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, recvWindow }) => { - try { - const params: any = { asset }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dustTransfer(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDustTransfer", + { + description: "Convert dust assets to BNB.", + inputSchema: { + asset: z.array(z.string()).describe("Array of asset symbols to convert"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, recvWindow }) => { + try { + const params: any = { asset }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dustTransfer(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Dust transfer completed. Total BNB received: ${data.totalServiceCharge || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Dust transfer completed. Total BNB received: ${data.totalServiceCharge || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to process dust transfer: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to process dust transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/dustlog.ts b/src/tools/binance-wallet/asset-api/dustlog.ts index 9ad92947..c1ccd2d6 100644 --- a/src/tools/binance-wallet/asset-api/dustlog.ts +++ b/src/tools/binance-wallet/asset-api/dustlog.ts @@ -1,44 +1,47 @@ // src/tools/binance-wallet/asset-api/dustlog.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDustlog(server: McpServer) { - server.tool( - "BinanceWalletDustlog", - "Get dust log (history of dust transfers).", - { - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ startTime, endTime, recvWindow }) => { - try { - const params: any = {}; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.dustlog(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDustlog", + { + description: "Get dust log (history of dust transfers).", + inputSchema: { + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ startTime, endTime, recvWindow }) => { + try { + const params: any = {}; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.dustlog(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved dust log. Total transfers: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved dust log. Total transfers: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve dust log: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve dust log: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/fundingWallet.ts b/src/tools/binance-wallet/asset-api/fundingWallet.ts index 0a08c73f..226a7bc6 100644 --- a/src/tools/binance-wallet/asset-api/fundingWallet.ts +++ b/src/tools/binance-wallet/asset-api/fundingWallet.ts @@ -1,44 +1,49 @@ // src/tools/binance-wallet/asset-api/fundingWallet.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFundingWallet(server: McpServer) { - server.tool( - "BinanceWalletFundingWallet", - "Get funding wallet balance.", - { - asset: z.string().optional().describe("Asset symbol"), - needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ asset, needBtcValuation, recvWindow }) => { - try { - const params: any = {}; - if (asset !== undefined) params.asset = asset; - if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.fundingWallet(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletFundingWallet", + { + description: "Get funding wallet balance.", + inputSchema: { + asset: z.string().optional().describe("Asset symbol"), + needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ asset, needBtcValuation, recvWindow }) => { + try { + const params: any = {}; + if (asset !== undefined) params.asset = asset; + if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.fundingWallet(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved funding wallet balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved funding wallet balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve funding wallet balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve funding wallet balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts b/src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts index 8c5a3ef1..f969e0c5 100644 --- a/src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts +++ b/src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts @@ -1,40 +1,47 @@ // src/tools/binance-wallet/asset-api/getAssetsThatCanBeConvertedIntoBnb.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server: McpServer) { - server.tool( - "BinanceWalletGetAssetsThatCanBeConvertedIntoBnb", - "Get assets that can be converted to BNB.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getAssetsThatCanBeConvertedIntoBnb(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetAssetsThatCanBeConvertedIntoBnb", + { + description: "Get assets that can be converted to BNB.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getAssetsThatCanBeConvertedIntoBnb( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved assets that can be converted to BNB. Total: ${data.details?.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved assets that can be converted to BNB. Total: ${data.details?.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve convertible assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve convertible assets: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts b/src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts index d8317c6b..4953b9e6 100644 --- a/src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts +++ b/src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts @@ -1,49 +1,56 @@ // src/tools/binance-wallet/asset-api/getCloudMiningPaymentAndRefundHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server: McpServer) { - server.tool( - "BinanceWalletGetCloudMiningPaymentAndRefundHistory", - "Get cloud mining payment and refund history.", - { - startTime: z.number().describe("Start time in milliseconds"), - endTime: z.number().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number"), - pageSize: z.number().optional().describe("Page size"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ startTime, endTime, page, pageSize, recvWindow }) => { - try { - const params: any = { - startTime, - endTime - }; - if (page !== undefined) params.page = page; - if (pageSize !== undefined) params.pageSize = pageSize; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.getCloudMiningPaymentAndRefundHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetCloudMiningPaymentAndRefundHistory", + { + description: "Get cloud mining payment and refund history.", + inputSchema: { + startTime: z.number().describe("Start time in milliseconds"), + endTime: z.number().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number"), + pageSize: z.number().optional().describe("Page size"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ startTime, endTime, page, pageSize, recvWindow }) => { + try { + const params: any = { + startTime, + endTime, + }; + if (page !== undefined) params.page = page; + if (pageSize !== undefined) params.pageSize = pageSize; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.getCloudMiningPaymentAndRefundHistory( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved cloud mining payment and refund history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved cloud mining payment and refund history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve cloud mining history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve cloud mining history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/getOpenSymbolList.ts b/src/tools/binance-wallet/asset-api/getOpenSymbolList.ts index dee5dbcf..ce26b78e 100644 --- a/src/tools/binance-wallet/asset-api/getOpenSymbolList.ts +++ b/src/tools/binance-wallet/asset-api/getOpenSymbolList.ts @@ -1,35 +1,33 @@ // src/tools/binance-wallet/asset-api/getOpenSymbolList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetOpenSymbolList(server: McpServer) { - server.tool( - "BinanceWalletGetOpenSymbolList", - "Get open symbol list.", - {}, - async () => { - try { - const response = await walletClient.restAPI.getOpenSymbolList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetOpenSymbolList", + { description: "Get open symbol list." }, + async () => { + try { + const response = await (walletClient as any).restAPI.getOpenSymbolList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved open symbol list. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved open symbol list. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve open symbol list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve open symbol list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/index.ts b/src/tools/binance-wallet/asset-api/index.ts index c3d59031..d06e8cd3 100644 --- a/src/tools/binance-wallet/asset-api/index.ts +++ b/src/tools/binance-wallet/asset-api/index.ts @@ -1,35 +1,36 @@ // src/tools/binance-wallet/asset-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletUserAsset } from "./userAsset.js"; -import { registerBinanceWalletFundingWallet } from "./fundingWallet.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAssetDetail } from "./assetDetail.js"; -import { registerBinanceWalletTradeFee } from "./tradeFee.js"; -import { registerBinanceWalletUserUniversalTransfer } from "./userUniversalTransfer.js"; -import { registerBinanceWalletQueryUserUniversalTransferHistory } from "./queryUserUniversalTransferHistory.js"; -import { registerBinanceWalletDustTransfer } from "./dustTransfer.js"; -import { registerBinanceWalletDustlog } from "./dustlog.js"; import { registerBinanceWalletAssetDividendRecord } from "./assetDividendRecord.js"; +import { registerBinanceWalletDustlog } from "./dustlog.js"; +import { registerBinanceWalletDustTransfer } from "./dustTransfer.js"; +import { registerBinanceWalletFundingWallet } from "./fundingWallet.js"; import { registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb } from "./getAssetsThatCanBeConvertedIntoBnb.js"; -import { registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest } from "./toggleBnbBurnOnSpotTradeAndMarginInterest.js"; import { registerBinanceWalletGetCloudMiningPaymentAndRefundHistory } from "./getCloudMiningPaymentAndRefundHistory.js"; -import { registerBinanceWalletQueryUserDelegationHistory } from "./queryUserDelegationHistory.js"; import { registerBinanceWalletGetOpenSymbolList } from "./getOpenSymbolList.js"; +import { registerBinanceWalletQueryUserDelegationHistory } from "./queryUserDelegationHistory.js"; +import { registerBinanceWalletQueryUserUniversalTransferHistory } from "./queryUserUniversalTransferHistory.js"; import { registerBinanceWalletQueryUserWalletBalance } from "./queryUserWalletBalance.js"; +import { registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest } from "./toggleBnbBurnOnSpotTradeAndMarginInterest.js"; +import { registerBinanceWalletTradeFee } from "./tradeFee.js"; +import { registerBinanceWalletUserAsset } from "./userAsset.js"; +import { registerBinanceWalletUserUniversalTransfer } from "./userUniversalTransfer.js"; export function registerBinanceWalletAssetApiTools(server: McpServer) { - registerBinanceWalletUserAsset(server); - registerBinanceWalletFundingWallet(server); - registerBinanceWalletAssetDetail(server); - registerBinanceWalletTradeFee(server); - registerBinanceWalletUserUniversalTransfer(server); - registerBinanceWalletQueryUserUniversalTransferHistory(server); - registerBinanceWalletDustTransfer(server); - registerBinanceWalletDustlog(server); - registerBinanceWalletAssetDividendRecord(server); - registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server); - registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server); - registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server); - registerBinanceWalletQueryUserDelegationHistory(server); - registerBinanceWalletGetOpenSymbolList(server); - registerBinanceWalletQueryUserWalletBalance(server); -} \ No newline at end of file + registerBinanceWalletUserAsset(server); + registerBinanceWalletFundingWallet(server); + registerBinanceWalletAssetDetail(server); + registerBinanceWalletTradeFee(server); + registerBinanceWalletUserUniversalTransfer(server); + registerBinanceWalletQueryUserUniversalTransferHistory(server); + registerBinanceWalletDustTransfer(server); + registerBinanceWalletDustlog(server); + registerBinanceWalletAssetDividendRecord(server); + registerBinanceWalletGetAssetsThatCanBeConvertedIntoBnb(server); + registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server); + registerBinanceWalletGetCloudMiningPaymentAndRefundHistory(server); + registerBinanceWalletQueryUserDelegationHistory(server); + registerBinanceWalletGetOpenSymbolList(server); + registerBinanceWalletQueryUserWalletBalance(server); +} diff --git a/src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts b/src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts index 02075a79..b2e75a0f 100644 --- a/src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts +++ b/src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts @@ -1,51 +1,56 @@ // src/tools/binance-wallet/asset-api/queryUserDelegationHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserDelegationHistory(server: McpServer) { - server.tool( - "BinanceWalletQueryUserDelegationHistory", - "Query user delegation history.", - { - email: z.string().describe("Email address"), - startTime: z.number().describe("Start time in milliseconds"), - endTime: z.number().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number"), - limit: z.number().optional().describe("Results per page"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ email, startTime, endTime, page, limit, recvWindow }) => { - try { - const params: any = { - email, - startTime, - endTime - }; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserDelegationHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserDelegationHistory", + { + description: "Query user delegation history.", + inputSchema: { + email: z.string().describe("Email address"), + startTime: z.number().describe("Start time in milliseconds"), + endTime: z.number().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number"), + limit: z.number().optional().describe("Results per page"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, startTime, endTime, page, limit, recvWindow }) => { + try { + const params: any = { + email, + startTime, + endTime, + }; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserDelegationHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user delegation history. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user delegation history. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user delegation history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve user delegation history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts b/src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts index 59e3fca7..edfa2703 100644 --- a/src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts +++ b/src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts @@ -1,53 +1,63 @@ // src/tools/binance-wallet/asset-api/queryUserUniversalTransferHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserUniversalTransferHistory(server: McpServer) { - server.tool( - "BinanceWalletQueryUserUniversalTransferHistory", - "Query universal transfer history.", - { - type: z.string().describe("Transfer type"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - current: z.number().optional().describe("Current page"), - size: z.number().optional().describe("Page size"), - fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, startTime, endTime, current, size, fromSymbol, toSymbol, recvWindow }) => { - try { - const params: any = { type }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (current !== undefined) params.current = current; - if (size !== undefined) params.size = size; - if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; - if (toSymbol !== undefined) params.toSymbol = toSymbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserUniversalTransferHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserUniversalTransferHistory", + { + description: "Query universal transfer history.", + inputSchema: { + type: z.string().describe("Transfer type"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + current: z.number().optional().describe("Current page"), + size: z.number().optional().describe("Page size"), + fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, startTime, endTime, current, size, fromSymbol, toSymbol, recvWindow }) => { + try { + const params: any = { type }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (current !== undefined) params.current = current; + if (size !== undefined) params.size = size; + if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; + if (toSymbol !== undefined) params.toSymbol = toSymbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserUniversalTransferHistory( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved universal transfer history. Total: ${data.total || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved universal transfer history. Total: ${data.total || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve universal transfer history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to retrieve universal transfer history: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts b/src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts index b386a6d5..2a1520fb 100644 --- a/src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts +++ b/src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts @@ -1,40 +1,45 @@ // src/tools/binance-wallet/asset-api/queryUserWalletBalance.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletQueryUserWalletBalance(server: McpServer) { - server.tool( - "BinanceWalletQueryUserWalletBalance", - "Query user wallet balance.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.queryUserWalletBalance(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletQueryUserWalletBalance", + { + description: "Query user wallet balance.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.queryUserWalletBalance(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user wallet balance. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user wallet balance. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user wallet balance: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve user wallet balance: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts b/src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts index bf05c09b..688fcb5b 100644 --- a/src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts +++ b/src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts @@ -1,44 +1,49 @@ // src/tools/binance-wallet/asset-api/toggleBnbBurnOnSpotTradeAndMarginInterest.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest(server: McpServer) { - server.tool( - "BinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest", - "Toggle BNB burn on spot trade and margin interest.", - { - spotBNBBurn: z.string().optional().describe("'true' or 'false' for spot trade"), - interestBNBBurn: z.string().optional().describe("'true' or 'false' for margin interest"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ spotBNBBurn, interestBNBBurn, recvWindow }) => { - try { - const params: any = {}; - if (spotBNBBurn !== undefined) params.spotBNBBurn = spotBNBBurn; - if (interestBNBBurn !== undefined) params.interestBNBBurn = interestBNBBurn; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.toggleBnbBurnOnSpotTradeAndMarginInterest(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletToggleBnbBurnOnSpotTradeAndMarginInterest", + { + description: "Toggle BNB burn on spot trade and margin interest.", + inputSchema: { + spotBNBBurn: z.string().optional().describe("'true' or 'false' for spot trade"), + interestBNBBurn: z.string().optional().describe("'true' or 'false' for margin interest"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ spotBNBBurn, interestBNBBurn, recvWindow }) => { + try { + const params: any = {}; + if (spotBNBBurn !== undefined) params.spotBNBBurn = spotBNBBurn; + if (interestBNBBurn !== undefined) params.interestBNBBurn = interestBNBBurn; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await ( + walletClient as any + ).restAPI.toggleBnbBurnOnSpotTradeAndMarginInterest(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `BNB burn settings updated. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `BNB burn settings updated. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to update BNB burn settings: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to update BNB burn settings: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/tradeFee.ts b/src/tools/binance-wallet/asset-api/tradeFee.ts index e1a613a0..6861de41 100644 --- a/src/tools/binance-wallet/asset-api/tradeFee.ts +++ b/src/tools/binance-wallet/asset-api/tradeFee.ts @@ -1,42 +1,47 @@ // src/tools/binance-wallet/asset-api/tradeFee.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletTradeFee(server: McpServer) { - server.tool( - "BinanceWalletTradeFee", - "Get trade fee.", - { - symbol: z.string().optional().describe("Trading pair symbol"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ symbol, recvWindow }) => { - try { - const params: any = {}; - if (symbol !== undefined) params.symbol = symbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.tradeFee(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletTradeFee", + { + description: "Get trade fee.", + inputSchema: { + symbol: z.string().optional().describe("Trading pair symbol"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ symbol, recvWindow }) => { + try { + const params: any = {}; + if (symbol !== undefined) params.symbol = symbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.tradeFee(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved trade fee information. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved trade fee information. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve trade fee information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve trade fee information: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/userAsset.ts b/src/tools/binance-wallet/asset-api/userAsset.ts index f0d373e6..b9122d07 100644 --- a/src/tools/binance-wallet/asset-api/userAsset.ts +++ b/src/tools/binance-wallet/asset-api/userAsset.ts @@ -1,42 +1,45 @@ // src/tools/binance-wallet/asset-api/userAsset.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletUserAsset(server: McpServer) { - server.tool( - "BinanceWalletUserAsset", - "Get user assets.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation") - }, - async ({ recvWindow, needBtcValuation }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; - - const response = await walletClient.restAPI.userAsset(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletUserAsset", + { + description: "Get user assets.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + needBtcValuation: z.boolean().optional().describe("Whether to include BTC valuation"), + }, + }, + async ({ recvWindow, needBtcValuation }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + if (needBtcValuation !== undefined) params.needBtcValuation = needBtcValuation; + + const response = await (walletClient as any).restAPI.userAsset(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved user assets. Number of assets: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved user assets. Number of assets: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve user assets: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve user assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/asset-api/userUniversalTransfer.ts b/src/tools/binance-wallet/asset-api/userUniversalTransfer.ts index 3f9cf173..0f9527e2 100644 --- a/src/tools/binance-wallet/asset-api/userUniversalTransfer.ts +++ b/src/tools/binance-wallet/asset-api/userUniversalTransfer.ts @@ -1,52 +1,56 @@ - // src/tools/binance-wallet/asset-api/userUniversalTransfer.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletUserUniversalTransfer(server: McpServer) { - server.tool( - "BinanceWalletUserUniversalTransfer", - "Make universal transfer between different accounts.", - { - type: z.string().describe("Transfer type"), - asset: z.string().describe("Asset symbol"), - amount: z.number().describe("Transfer amount"), - fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ type, asset, amount, fromSymbol, toSymbol, recvWindow }) => { - try { - const params: any = { - type, - asset, - amount - }; - if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; - if (toSymbol !== undefined) params.toSymbol = toSymbol; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.userUniversalTransfer(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletUserUniversalTransfer", + { + description: "Make universal transfer between different accounts.", + inputSchema: { + type: z.string().describe("Transfer type"), + asset: z.string().describe("Asset symbol"), + amount: z.number().describe("Transfer amount"), + fromSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + toSymbol: z.string().optional().describe("Symbol for spot/margin trade pair"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ type, asset, amount, fromSymbol, toSymbol, recvWindow }) => { + try { + const params: any = { + type, + asset, + amount, + }; + if (fromSymbol !== undefined) params.fromSymbol = fromSymbol; + if (toSymbol !== undefined) params.toSymbol = toSymbol; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.userUniversalTransfer(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Universal transfer completed. Transfer ID: ${data.tranId}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Universal transfer completed. Transfer ID: ${data.tranId}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to process universal transfer: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to process universal transfer: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/allCoinsInformation.ts b/src/tools/binance-wallet/capital-api/allCoinsInformation.ts index 1dc48aad..5d998209 100644 --- a/src/tools/binance-wallet/capital-api/allCoinsInformation.ts +++ b/src/tools/binance-wallet/capital-api/allCoinsInformation.ts @@ -1,40 +1,43 @@ // src/tools/binance-wallet/capital-api/allCoinsInformation.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletAllCoinsInformation(server: McpServer) { - server.tool( - "BinanceWalletAllCoinsInformation", - "Get information for all coins.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ recvWindow }) => { - try { - const params: any = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.allCoinsInformation(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletAllCoinsInformation", + { + description: "Get information for all coins.", + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: any = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.allCoinsInformation(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved information for all coins. Total coins: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved information for all coins. Total coins: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve coin information: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve coin information: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/depositAddress.ts b/src/tools/binance-wallet/capital-api/depositAddress.ts index cbcc2d66..0ecb0015 100644 --- a/src/tools/binance-wallet/capital-api/depositAddress.ts +++ b/src/tools/binance-wallet/capital-api/depositAddress.ts @@ -1,43 +1,46 @@ // src/tools/binance-wallet/capital-api/depositAddress.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositAddress(server: McpServer) { - server.tool( - "BinanceWalletDepositAddress", - "Get deposit address for a specific coin.", - { - coin: z.string().describe("Coin symbol"), - network: z.string().optional().describe("Network"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, network, recvWindow }) => { - try { - const params: any = { coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.depositAddress(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDepositAddress", + { + description: "Get deposit address for a specific coin.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + network: z.string().optional().describe("Network"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, recvWindow }) => { + try { + const params: any = { coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositAddress(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit address for ${coin}. Address: ${data.address}${data.tag ? `, Tag: ${data.tag}` : ""}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit address for ${coin}. Address: ${data.address}${data.tag ? `, Tag: ${data.tag}` : ''}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit address: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit address: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/depositHistory.ts b/src/tools/binance-wallet/capital-api/depositHistory.ts index 20c3ed33..67729320 100644 --- a/src/tools/binance-wallet/capital-api/depositHistory.ts +++ b/src/tools/binance-wallet/capital-api/depositHistory.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/capital-api/depositHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositHistory(server: McpServer) { - server.tool( - "BinanceWalletDepositHistory", - "Get deposit history.", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Deposit status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Pagination offset"), - limit: z.number().optional().describe("Number of records to return"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; + server.registerTool( + "BinanceWalletDepositHistory", + { + description: "Get deposit history.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Deposit status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Pagination offset"), + limit: z.number().optional().describe("Number of records to return"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositHistory(params); + const data = await response.data(); - const response = await walletClient.restAPI.depositHistory(params); - const data = await response.data(); + return { + content: [ + { + type: "text", + text: `Retrieved deposit history. Total deposits: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit history. Total deposits: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts b/src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts index a9b87324..684fa6c5 100644 --- a/src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts +++ b/src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts @@ -1,43 +1,50 @@ // src/tools/binance-wallet/capital-api/fetchDepositAddressListWithNetwork.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFetchDepositAddressListWithNetwork(server: McpServer) { - server.tool( - "BinanceWalletFetchDepositAddressListWithNetwork", - "Fetch deposit address with network.", - { - coin: z.string().describe("Coin symbol"), - network: z.string().optional().describe("Network"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, network, recvWindow }) => { - try { - const params: any = { coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.fetchDepositAddressListWithNetwork(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletFetchDepositAddressListWithNetwork", + { + description: "Fetch deposit address with network.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + network: z.string().optional().describe("Network"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, recvWindow }) => { + try { + const params: any = { coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.fetchDepositAddressListWithNetwork( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit addresses for ${coin}. Total addresses: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit addresses for ${coin}. Total addresses: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit addresses: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve deposit addresses: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts b/src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts index 1aa56a22..10f899eb 100644 --- a/src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts +++ b/src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts @@ -1,37 +1,35 @@ // src/tools/binance-wallet/capital-api/fetchWithdrawAddressList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletFetchWithdrawAddressList(server: McpServer) { - server.tool( - "BinanceWalletFetchWithdrawAddressList", - "Fetch withdraw address list.", - { - }, - async () => { - try { - - const response = await walletClient.restAPI.fetchWithdrawAddressList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletFetchWithdrawAddressList", + { description: "Fetch withdraw address list." }, + async () => { + try { + const response = await (walletClient as any).restAPI.fetchWithdrawAddressList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw address list. Total addresses: ${data || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw address list. Total addresses: ${data || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw address list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve withdraw address list: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/index.ts b/src/tools/binance-wallet/capital-api/index.ts index be8c1ac1..f1086cd9 100644 --- a/src/tools/binance-wallet/capital-api/index.ts +++ b/src/tools/binance-wallet/capital-api/index.ts @@ -1,21 +1,22 @@ // src/tools/binance-wallet/capital-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAllCoinsInformation } from "./allCoinsInformation.js"; import { registerBinanceWalletDepositAddress } from "./depositAddress.js"; import { registerBinanceWalletDepositHistory } from "./depositHistory.js"; -import { registerBinanceWalletWithdrawHistory } from "./withdrawHistory.js"; -import { registerBinanceWalletWithdraw } from "./withdraw.js"; import { registerBinanceWalletFetchDepositAddressListWithNetwork } from "./fetchDepositAddressListWithNetwork.js"; import { registerBinanceWalletFetchWithdrawAddressList } from "./fetchWithdrawAddressList.js"; import { registerBinanceWalletOneClickArrivalDepositApply } from "./oneClickArrivalDepositApply.js"; +import { registerBinanceWalletWithdraw } from "./withdraw.js"; +import { registerBinanceWalletWithdrawHistory } from "./withdrawHistory.js"; export function registerBinanceWalletCapitalApiTools(server: McpServer) { - registerBinanceWalletAllCoinsInformation(server); - registerBinanceWalletDepositAddress(server); - registerBinanceWalletDepositHistory(server); - registerBinanceWalletWithdrawHistory(server); - registerBinanceWalletWithdraw(server); - registerBinanceWalletFetchDepositAddressListWithNetwork(server); - registerBinanceWalletFetchWithdrawAddressList(server); - registerBinanceWalletOneClickArrivalDepositApply(server); -} \ No newline at end of file + registerBinanceWalletAllCoinsInformation(server); + registerBinanceWalletDepositAddress(server); + registerBinanceWalletDepositHistory(server); + registerBinanceWalletWithdrawHistory(server); + registerBinanceWalletWithdraw(server); + registerBinanceWalletFetchDepositAddressListWithNetwork(server); + registerBinanceWalletFetchWithdrawAddressList(server); + registerBinanceWalletOneClickArrivalDepositApply(server); +} diff --git a/src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts b/src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts index 8ecc17ed..794acc72 100644 --- a/src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts +++ b/src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts @@ -1,42 +1,50 @@ // src/tools/binance-wallet/capital-api/oneClickArrivalDepositApply.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletOneClickArrivalDepositApply(server: McpServer) { - server.tool( - "BinanceWalletOneClickArrivalDepositApply", - "Apply for one-click arrival deposit.", - { - subAccountId: z.string().optional().describe("Sub-account ID"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, recvWindow }) => { - try { - const params: any = {}; - if (subAccountId !== undefined) params.subAccountId = subAccountId; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.oneClickArrivalDepositApply(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletOneClickArrivalDepositApply", + { + description: "Apply for one-click arrival deposit.", + inputSchema: { + subAccountId: z.string().optional().describe("Sub-account ID"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, recvWindow }) => { + try { + const params: any = {}; + if (subAccountId !== undefined) params.subAccountId = subAccountId; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.oneClickArrivalDepositApply(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Applied for one-click arrival deposit. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Applied for one-click arrival deposit. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to apply for one-click arrival deposit: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to apply for one-click arrival deposit: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/withdraw.ts b/src/tools/binance-wallet/capital-api/withdraw.ts index 50e4c1a6..c759c25a 100644 --- a/src/tools/binance-wallet/capital-api/withdraw.ts +++ b/src/tools/binance-wallet/capital-api/withdraw.ts @@ -1,59 +1,73 @@ // src/tools/binance-wallet/capital-api/withdraw.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdraw(server: McpServer) { - server.tool( - "BinanceWalletWithdraw", - "Submit a withdraw request.", - { - coin: z.string().describe("Coin symbol"), - address: z.string().describe("Withdrawal address"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().optional().describe("Client order id"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier (tag/memo)"), - name: z.string().optional().describe("Address name"), - walletType: z.number().optional().describe("Wallet type"), - transactionFeeFlag: z.boolean().optional().describe("Pay fee with BNB"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, address, amount, withdrawOrderId, network, addressTag, name, walletType, transactionFeeFlag, recvWindow }) => { - try { - const params: any = { - coin, - address, - amount - }; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (walletType !== undefined) params.walletType = walletType; - if (transactionFeeFlag !== undefined) params.transactionFeeFlag = transactionFeeFlag; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdraw(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdraw", + { + description: "Submit a withdraw request.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + address: z.string().describe("Withdrawal address"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().optional().describe("Client order id"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier (tag/memo)"), + name: z.string().optional().describe("Address name"), + walletType: z.number().optional().describe("Wallet type"), + transactionFeeFlag: z.boolean().optional().describe("Pay fee with BNB"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + coin, + address, + amount, + withdrawOrderId, + network, + addressTag, + name, + walletType, + transactionFeeFlag, + recvWindow, + }) => { + try { + const params: any = { + coin, + address, + amount, + }; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (walletType !== undefined) params.walletType = walletType; + if (transactionFeeFlag !== undefined) params.transactionFeeFlag = transactionFeeFlag; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdraw(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Withdraw request submitted. Withdrawal ID: ${data.id}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Withdraw request submitted. Withdrawal ID: ${data.id}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit withdraw request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to submit withdraw request: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/capital-api/withdrawHistory.ts b/src/tools/binance-wallet/capital-api/withdrawHistory.ts index f846925c..e9c7cec7 100644 --- a/src/tools/binance-wallet/capital-api/withdrawHistory.ts +++ b/src/tools/binance-wallet/capital-api/withdrawHistory.ts @@ -1,54 +1,57 @@ // src/tools/binance-wallet/capital-api/withdrawHistory.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistory(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistory", - "Get withdraw history.", - { - coin: z.string().optional().describe("Coin symbol"), - withdrawOrderId: z.string().optional().describe("Withdraw order ID"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Pagination offset"), - limit: z.number().optional().describe("Number of records to return"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistory(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistory", + { + description: "Get withdraw history.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + withdrawOrderId: z.string().optional().describe("Withdraw order ID"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Pagination offset"), + limit: z.number().optional().describe("Number of records to return"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistory(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history. Total withdrawals: ${data.length || 0}. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history. Total withdrawals: ${data.length || 0}. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/index.ts b/src/tools/binance-wallet/index.ts index e3e85d29..89694cce 100644 --- a/src/tools/binance-wallet/index.ts +++ b/src/tools/binance-wallet/index.ts @@ -1,24 +1,25 @@ // src/tools/binance-wallet/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletAccountApiTools } from "./account-api/index.js"; -import { registerBinanceWalletOthersApiTools } from "./others-api/index.js"; -import { registerBinanceWalletTravelRuleApiTools } from "./travel-rule-api/index.js"; import { registerBinanceWalletAssetApiTools } from "./asset-api/index.js"; import { registerBinanceWalletCapitalApiTools } from "./capital-api/index.js"; +import { registerBinanceWalletOthersApiTools } from "./others-api/index.js"; +import { registerBinanceWalletTravelRuleApiTools } from "./travel-rule-api/index.js"; export function registerBinanceWalletTools(server: McpServer) { - // Account API tools - registerBinanceWalletAccountApiTools(server); - - // Others API tools - registerBinanceWalletOthersApiTools(server); - - // Travel Rule API tools - registerBinanceWalletTravelRuleApiTools(server); - - // Asset API tools - registerBinanceWalletAssetApiTools(server); - - // Capital API tools - registerBinanceWalletCapitalApiTools(server); -} \ No newline at end of file + // Account API tools + registerBinanceWalletAccountApiTools(server); + + // Others API tools + registerBinanceWalletOthersApiTools(server); + + // Travel Rule API tools + registerBinanceWalletTravelRuleApiTools(server); + + // Asset API tools + registerBinanceWalletAssetApiTools(server); + + // Capital API tools + registerBinanceWalletCapitalApiTools(server); +} diff --git a/src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts b/src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts index f1c4f0f6..3ef67fe7 100644 --- a/src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts +++ b/src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts @@ -1,34 +1,33 @@ // src/tools/binance-wallet/others-api/getSymbolsDelistScheduleForSpot.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletGetSymbolsDelistScheduleForSpot(server: McpServer) { - server.tool( - "BinanceWalletGetSymbolsDelistScheduleForSpot", - "Get delist schedule for spot symbols.", - {}, - async () => { - try { - const response = await walletClient.restAPI.getSymbolsDelistScheduleForSpot(); - const data = await response.data(); + server.registerTool( + "BinanceWalletGetSymbolsDelistScheduleForSpot", + { description: "Get delist schedule for spot symbols." }, + async () => { + try { + const response = await (walletClient as any).restAPI.getSymbolsDelistScheduleForSpot(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved delist schedule for spot symbols. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved delist schedule for spot symbols. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve delist schedule: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve delist schedule: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/others-api/index.ts b/src/tools/binance-wallet/others-api/index.ts index d0ca0559..e1f899e4 100644 --- a/src/tools/binance-wallet/others-api/index.ts +++ b/src/tools/binance-wallet/others-api/index.ts @@ -1,10 +1,10 @@ //src/tools/binance-wallet/others-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceWalletSystemStatus } from "./systemStatus.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletGetSymbolsDelistScheduleForSpot } from "./getSymbolsDelistScheduleForSpot.js"; +import { registerBinanceWalletSystemStatus } from "./systemStatus.js"; export function registerBinanceWalletOthersApiTools(server: McpServer) { - registerBinanceWalletSystemStatus(server); - registerBinanceWalletGetSymbolsDelistScheduleForSpot(server); - -} \ No newline at end of file + registerBinanceWalletSystemStatus(server); + registerBinanceWalletGetSymbolsDelistScheduleForSpot(server); +} diff --git a/src/tools/binance-wallet/others-api/systemStatus.ts b/src/tools/binance-wallet/others-api/systemStatus.ts index 57e4133e..f218dcdd 100644 --- a/src/tools/binance-wallet/others-api/systemStatus.ts +++ b/src/tools/binance-wallet/others-api/systemStatus.ts @@ -1,34 +1,33 @@ // src/tools/binance-wallet/others-api/systemStatus.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSystemStatus(server: McpServer) { - server.tool( - "BinanceWalletSystemStatus", - "Get Binance Wallet system status.", - {}, - async () => { - try { - const response = await walletClient.restAPI.systemStatus(); - const data = await response.data(); + server.registerTool( + "BinanceWalletSystemStatus", + { description: "Get Binance Wallet system status." }, + async () => { + try { + const response = await (walletClient as any).restAPI.systemStatus(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved system status. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved system status. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve system status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve system status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts b/src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts index 08be01e6..e2a34782 100644 --- a/src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts +++ b/src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts @@ -1,63 +1,81 @@ // src/tools/binance-wallet/travel-rule-api/brokerWithdraw.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletBrokerWithdraw(server: McpServer) { - server.tool( - "BinanceWalletBrokerWithdraw", - "Initiate broker withdrawal with travel rule compliance.", - { - subAccountId: z.string().describe("Sub-account ID"), - address: z.string().describe("Withdrawal address"), - coin: z.string().describe("Coin symbol"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().describe("Client order id"), - questionnaire: z.string().describe("Travel rule questionnaire"), - originatorPii: z.string().describe("Originator PII information"), - signature: z.string().describe("Signature"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier"), - name: z.string().optional().describe("Address name"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, address, coin, amount, withdrawOrderId, questionnaire, originatorPii, signature, network, addressTag, name, recvWindow }) => { - try { - const params: any = { - subAccountId, - address, - coin, - amount, - withdrawOrderId, - questionnaire, - originatorPii, - signature - }; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.brokerWithdraw(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletBrokerWithdraw", + { + description: "Initiate broker withdrawal with travel rule compliance.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + address: z.string().describe("Withdrawal address"), + coin: z.string().describe("Coin symbol"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().describe("Client order id"), + questionnaire: z.string().describe("Travel rule questionnaire"), + originatorPii: z.string().describe("Originator PII information"), + signature: z.string().describe("Signature"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier"), + name: z.string().optional().describe("Address name"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + subAccountId, + address, + coin, + amount, + withdrawOrderId, + questionnaire, + originatorPii, + signature, + network, + addressTag, + name, + recvWindow, + }) => { + try { + const params: any = { + subAccountId, + address, + coin, + amount, + withdrawOrderId, + questionnaire, + originatorPii, + signature, + }; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.brokerWithdraw(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Broker withdraw request submitted. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Broker withdraw request submitted. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit broker withdraw request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit broker withdraw request: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts b/src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts index e86c7efa..4ef383c4 100644 --- a/src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts +++ b/src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/depositHistoryTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletDepositHistoryTravelRule(server: McpServer) { - server.tool( - "BinanceWalletDepositHistoryTravelRule", - "Get deposit history for travel rule.", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Deposit status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.depositHistoryTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletDepositHistoryTravelRule", + { + description: "Get deposit history for travel rule.", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Deposit status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.depositHistoryTravelRule(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved deposit history for travel rule. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved deposit history for travel rule. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/index.ts b/src/tools/binance-wallet/travel-rule-api/index.ts index 5cafccd8..f475165d 100644 --- a/src/tools/binance-wallet/travel-rule-api/index.ts +++ b/src/tools/binance-wallet/travel-rule-api/index.ts @@ -1,22 +1,22 @@ //src/tools/binance-wallet/travel-rule-api/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceWalletBrokerWithdraw } from "./brokerWithdraw.js"; +import { registerBinanceWalletDepositHistoryTravelRule } from "./depositHistoryTravelRule.js"; import { registerBinanceWalletOnboardedVaspList } from "./onboardedVaspList.js"; import { registerBinanceWalletSubmitDepositQuestionnaire } from "./submitDepositQuestionnaire.js"; +import { registerBinanceWalletSubmitDepositQuestionnaireTravelRule } from "./submitDepositQuestionnaireTravelRule.js"; import { registerBinanceWalletWithdrawHistoryV1 } from "./withdrawHistoryV1.js"; -import { registerBinanceWalletDepositHistoryTravelRule } from "./depositHistoryTravelRule.js"; import { registerBinanceWalletWithdrawHistoryV2 } from "./withdrawHistoryV2.js"; import { registerBinanceWalletWithdrawTravelRule } from "./withdrawTravelRule.js"; -import { registerBinanceWalletSubmitDepositQuestionnaireTravelRule } from "./submitDepositQuestionnaireTravelRule.js"; export function registerBinanceWalletTravelRuleApiTools(server: McpServer) { - registerBinanceWalletBrokerWithdraw(server); - registerBinanceWalletOnboardedVaspList(server); - registerBinanceWalletSubmitDepositQuestionnaire(server); - registerBinanceWalletWithdrawHistoryV1(server); - registerBinanceWalletDepositHistoryTravelRule(server); - registerBinanceWalletWithdrawHistoryV2(server); - registerBinanceWalletWithdrawTravelRule(server); - registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server); - -} \ No newline at end of file + registerBinanceWalletBrokerWithdraw(server); + registerBinanceWalletOnboardedVaspList(server); + registerBinanceWalletSubmitDepositQuestionnaire(server); + registerBinanceWalletWithdrawHistoryV1(server); + registerBinanceWalletDepositHistoryTravelRule(server); + registerBinanceWalletWithdrawHistoryV2(server); + registerBinanceWalletWithdrawTravelRule(server); + registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server); +} diff --git a/src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts b/src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts index d78089c6..8b063cf5 100644 --- a/src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts +++ b/src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts @@ -1,35 +1,35 @@ // src/tools/binance-wallet/travel-rule-api/onboardedVaspList.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletOnboardedVaspList(server: McpServer) { - server.tool( - "BinanceWalletOnboardedVaspList", - "Get list of onboarded VASPs (Virtual Asset Service Providers).", - {}, - async () => { - try { - const response = await walletClient.restAPI.onboardedVaspList(); - const data = await response.data(); + server.registerTool( + "BinanceWalletOnboardedVaspList", + { description: "Get list of onboarded VASPs (Virtual Asset Service Providers)." }, + async () => { + try { + const response = await (walletClient as any).restAPI.onboardedVaspList(); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved onboarded VASP list. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved onboarded VASP list. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve onboarded VASP list: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to retrieve onboarded VASP list: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts b/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts index 37ef2dc6..350be6f0 100644 --- a/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts +++ b/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts @@ -1,51 +1,56 @@ // src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaire.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSubmitDepositQuestionnaire(server: McpServer) { - server.tool( - "BinanceWalletSubmitDepositQuestionnaire", - "Submit deposit questionnaire for broker deposit.", - { - subAccountId: z.string().describe("Sub-account ID"), - depositId: z.string().describe("Deposit ID"), - questionnaire: z.string().describe("Travel rule questionnaire"), - beneficiaryPii: z.string().describe("Beneficiary PII information"), - signature: z.string().describe("Signature"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ subAccountId, depositId, questionnaire, beneficiaryPii, signature, recvWindow }) => { - try { - const params: any = { - subAccountId, - depositId, - questionnaire, - beneficiaryPii, - signature - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.submitDepositQuestionnaire(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletSubmitDepositQuestionnaire", + { + description: "Submit deposit questionnaire for broker deposit.", + inputSchema: { + subAccountId: z.string().describe("Sub-account ID"), + depositId: z.string().describe("Deposit ID"), + questionnaire: z.string().describe("Travel rule questionnaire"), + beneficiaryPii: z.string().describe("Beneficiary PII information"), + signature: z.string().describe("Signature"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ subAccountId, depositId, questionnaire, beneficiaryPii, signature, recvWindow }) => { + try { + const params: any = { + subAccountId, + depositId, + questionnaire, + beneficiaryPii, + signature, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.submitDepositQuestionnaire(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Submitted deposit questionnaire for broker deposit. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Submitted deposit questionnaire for broker deposit. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts b/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts index 4d2f4f9e..95aadcf7 100644 --- a/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts +++ b/src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts @@ -1,45 +1,52 @@ // src/tools/binance-wallet/travel-rule-api/submitDepositQuestionnaireTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletSubmitDepositQuestionnaireTravelRule(server: McpServer) { - server.tool( - "BinanceWalletSubmitDepositQuestionnaireTravelRule", - "Submit deposit questionnaire for travel rule.", - { - tranId: z.number().describe("Transaction ID"), - questionnaire: z.string().describe("Travel rule questionnaire"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ tranId, questionnaire, recvWindow }) => { - try { - const params: any = { - tranId, - questionnaire - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.submitDepositQuestionnaireTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletSubmitDepositQuestionnaireTravelRule", + { + description: "Submit deposit questionnaire for travel rule.", + inputSchema: { + tranId: z.number().describe("Transaction ID"), + questionnaire: z.string().describe("Travel rule questionnaire"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ tranId, questionnaire, recvWindow }) => { + try { + const params: any = { + tranId, + questionnaire, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.submitDepositQuestionnaireTravelRule( + params, + ); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Submitted deposit questionnaire for travel rule. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Submitted deposit questionnaire for travel rule. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { type: "text", text: `Failed to submit deposit questionnaire: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts b/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts index 4cf980f9..9cdee180 100644 --- a/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts +++ b/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/withdrawHistoryV1.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistoryV1(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistoryV1", - "Get withdraw history (v1).", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistoryV1(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistoryV1", + { + description: "Get withdraw history (v1).", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistoryV1(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history v1. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history v1. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts b/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts index 2b20d3a2..596e4d97 100644 --- a/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts +++ b/src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts @@ -1,52 +1,55 @@ // src/tools/binance-wallet/travel-rule-api/withdrawHistoryV2.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawHistoryV2(server: McpServer) { - server.tool( - "BinanceWalletWithdrawHistoryV2", - "Get withdraw history (v2).", - { - coin: z.string().optional().describe("Coin symbol"), - status: z.number().optional().describe("Withdraw status"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - offset: z.number().optional().describe("Default 0"), - limit: z.number().optional().describe("Default 1000, max 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: any = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawHistoryV2(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawHistoryV2", + { + description: "Get withdraw history (v2).", + inputSchema: { + coin: z.string().optional().describe("Coin symbol"), + status: z.number().optional().describe("Withdraw status"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + offset: z.number().optional().describe("Default 0"), + limit: z.number().optional().describe("Default 1000, max 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: any = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawHistoryV2(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Retrieved withdraw history v2. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Retrieved withdraw history v2. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [{ type: "text", text: `Failed to retrieve withdraw history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts b/src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts index 5d7bd8bf..e0c08765 100644 --- a/src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts +++ b/src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts @@ -1,57 +1,75 @@ // src/tools/binance-wallet/travel-rule-api/withdrawTravelRule.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { walletClient } from "../../../config/binanceClient.js"; export function registerBinanceWalletWithdrawTravelRule(server: McpServer) { - server.tool( - "BinanceWalletWithdrawTravelRule", - "Withdraw with travel rule compliance.", - { - coin: z.string().describe("Coin symbol"), - address: z.string().describe("Withdrawal address"), - amount: z.number().describe("Withdrawal amount"), - withdrawOrderId: z.string().optional().describe("Client order id"), - network: z.string().optional().describe("Network"), - addressTag: z.string().optional().describe("Secondary address identifier"), - name: z.string().optional().describe("Address name"), - questionnaire: z.string().describe("Travel rule questionnaire"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async ({ coin, address, amount, withdrawOrderId, network, addressTag, name, questionnaire, recvWindow }) => { - try { - const params: any = { - coin, - address, - amount, - questionnaire - }; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (network !== undefined) params.network = network; - if (addressTag !== undefined) params.addressTag = addressTag; - if (name !== undefined) params.name = name; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const response = await walletClient.restAPI.withdrawTravelRule(params); - const data = await response.data(); + server.registerTool( + "BinanceWalletWithdrawTravelRule", + { + description: "Withdraw with travel rule compliance.", + inputSchema: { + coin: z.string().describe("Coin symbol"), + address: z.string().describe("Withdrawal address"), + amount: z.number().describe("Withdrawal amount"), + withdrawOrderId: z.string().optional().describe("Client order id"), + network: z.string().optional().describe("Network"), + addressTag: z.string().optional().describe("Secondary address identifier"), + name: z.string().optional().describe("Address name"), + questionnaire: z.string().describe("Travel rule questionnaire"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ + coin, + address, + amount, + withdrawOrderId, + network, + addressTag, + name, + questionnaire, + recvWindow, + }) => { + try { + const params: any = { + coin, + address, + amount, + questionnaire, + }; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (network !== undefined) params.network = network; + if (addressTag !== undefined) params.addressTag = addressTag; + if (name !== undefined) params.name = name; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const response = await (walletClient as any).restAPI.withdrawTravelRule(params); + const data = await response.data(); + + return { + content: [ + { + type: "text", + text: `Withdraw travel rule request submitted. Response: ${JSON.stringify(data)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { - type: "text", - text: `Withdraw travel rule request submitted. Response: ${JSON.stringify(data)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to submit withdraw travel rule request: ${errorMessage}` } - ], - isError: true - }; - } - } - ); -} \ No newline at end of file + return { + content: [ + { + type: "text", + text: `Failed to submit withdraw travel rule request: ${errorMessage}`, + }, + ], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binanceAccountInfo.ts b/src/tools/binanceAccountInfo.ts index 6706eee2..af9f9a5c 100644 --- a/src/tools/binanceAccountInfo.ts +++ b/src/tools/binanceAccountInfo.ts @@ -1,58 +1,68 @@ -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; -import { spotClient } from "../config/client.js"; -import { AccountSnapshotType } from "@binance/connector-typescript"; -export function registerBinanceAccountInfo(server: McpServer) { - server.tool( - "binanceAccountInfo", - "check binance account info", - {}, - async ({}) => { - try { - const accountInfo = await spotClient.accountInformation(); - const accountSnapshot = await spotClient.dailyAccountSnapshot(AccountSnapshotType.SPOT, { limit: 7 }); - const userAsset = await spotClient.userAsset({ needBtcValuation: true }) - if (userAsset) { - const balances = userAsset.map(item => ({ - asset: item.asset, free: item.free, locked: item.locked - })) - const totalAssetOfBtc = userAsset.reduce((sum, item) => sum + parseFloat(item.btcValuation || "0"), 0).toFixed(20).replace(/\.?0+$/, ""); - accountSnapshot.snapshotVos.push({ - type: "spot", - updateTime: Date.now(), - data: { - totalAssetOfBtc, - balances, - } - }) - } - const btcPrice = await spotClient.symbolPriceTicker({ symbol: "BTCUSDT" }); - return { - content: [ - { - type: "text", - text: `Get binance account info successfully. data: ${JSON.stringify(accountInfo)}`, - }, - { - type: "text", - text: `Get binance balance history info successfully. data: ${JSON.stringify(accountSnapshot)}`, - }, - { - type: "text", - text: `Get BTC price successfully. data: ${JSON.stringify(btcPrice)}`, - }, - ], - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Server failed: ${errorMessage}` }, - ], - isError: true, - }; - } - } - ); -} \ No newline at end of file +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { AccountSnapshotType } from "@binance/connector-typescript"; + +import { spotClient } from "../config/client.js"; +export function registerBinanceAccountInfo(server: McpServer) { + server.registerTool( + "binanceAccountInfo", + { description: "check binance account info" }, + async (_params) => { + try { + const accountInfo = await spotClient.accountInformation(); + const accountSnapshot = await spotClient.dailyAccountSnapshot(AccountSnapshotType.SPOT, { + limit: 7, + }); + const userAsset = await spotClient.userAsset({ + needBtcValuation: true, + }); + if (userAsset) { + const balances = userAsset.map((item) => ({ + asset: item.asset, + free: item.free, + locked: item.locked, + })); + const totalAssetOfBtc = userAsset + .reduce((sum, item) => sum + parseFloat(item.btcValuation || "0"), 0) + .toFixed(20) + .replace(/\.?0+$/, ""); + accountSnapshot.snapshotVos.push({ + type: "spot", + updateTime: Date.now(), + data: { + totalAssetOfBtc, + balances, + }, + }); + } + const btcPrice = await spotClient.symbolPriceTicker({ + symbol: "BTCUSDT", + }); + + return { + content: [ + { + type: "text", + text: `Get binance account info successfully. data: ${JSON.stringify(accountInfo)}`, + }, + { + type: "text", + text: `Get binance balance history info successfully. data: ${JSON.stringify(accountSnapshot)}`, + }, + { + type: "text", + text: `Get BTC price successfully. data: ${JSON.stringify(btcPrice)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Server failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binanceOrderBook.ts b/src/tools/binanceOrderBook.ts index 2a47d9ed..0f24ae55 100644 --- a/src/tools/binanceOrderBook.ts +++ b/src/tools/binanceOrderBook.ts @@ -1,37 +1,38 @@ -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; -import { spotClient } from "../config/client.js"; - -export function registerBinanceOrderBook(server: McpServer) { - server.tool( - "binanceOrderBook", - "check binance order book", - { - symbol: z.string().describe("symbol: exemple: BTCUSDT"), - }, - async ({ symbol }) => { - try { - - const orderBook = await spotClient.orderBook(symbol, {limit: 50}); - - return { - content: [ - { - type: "text", - text: `Get binance order book successfully. data: ${JSON.stringify(orderBook)}}`, - }, - ], - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Server failed: ${errorMessage}` }, - ], - isError: true, - }; - } - } - ); -} +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { z } from "zod"; + +import { spotClient } from "../config/client.js"; + +export function registerBinanceOrderBook(server: McpServer) { + server.registerTool( + "binanceOrderBook", + { + description: "check binance order book", + inputSchema: { + symbol: z.string().describe("symbol: exemple: BTCUSDT"), + }, + }, + async ({ symbol }) => { + try { + const orderBook = await spotClient.orderBook(symbol, { limit: 50 }); + + return { + content: [ + { + type: "text", + text: `Get binance order book successfully. data: ${JSON.stringify(orderBook)}}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Server failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binanceSpotPlaceOrder.ts b/src/tools/binanceSpotPlaceOrder.ts index 3e39982c..1aca1f9d 100644 --- a/src/tools/binanceSpotPlaceOrder.ts +++ b/src/tools/binanceSpotPlaceOrder.ts @@ -1,49 +1,54 @@ -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; -import { algoClient, spotClient } from "../config/client.js"; -import { OrderType, Side } from "@binance/connector-typescript"; - -export function registerBinanceSpotPlaceOrder(server: McpServer) { - server.tool( - "binanceSpotPlaceOrder", - `Trading for small orders will not generate significant selling pressure on the market`, - { - symbol: z.string().describe("symbol: exemple: BTCUSDT"), - side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), - quantity: z.number().describe("quantity Quantity of base asset").optional(), - quoteOrderQty: z.number().describe(`MARKET orders using quoteOrderQty specifies the amount the user wants to spend (when buying) or receive (when selling) the quote asset; the correct quantity will be determined based on the market liquidity and quoteOrderQty. - E.g. Using the symbol BTCUSDT: - BUY side, the order will buy as many BTC as quoteOrderQty USDT can. - SELL side, the order will sell as much BTC needed to receive quoteOrderQty USDT.`).optional(), - }, - async ({ symbol, side, quantity, quoteOrderQty }) => { - try { - - - const result = await spotClient.newOrder(symbol, side as Side, OrderType.MARKET, { - quantity, - quoteOrderQty, - }) - - - return { - content: [ - { - type: "text", - text: `Place a new spot TWAP order with Algo service successfully. result: ${JSON.stringify(result)}}`, - }, - ], - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Server failed: ${errorMessage}` }, - ], - isError: true, - }; - } - } - ); -} +import type { Side } from "@binance/connector-typescript"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { OrderType } from "@binance/connector-typescript"; +import { z } from "zod"; + +import { spotClient } from "../config/client.js"; + +export function registerBinanceSpotPlaceOrder(server: McpServer) { + server.registerTool( + "binanceSpotPlaceOrder", + { + description: `Trading for small orders will not generate significant selling pressure on the market`, + inputSchema: { + symbol: z.string().describe("symbol: exemple: BTCUSDT"), + side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), + quantity: z.number().describe("quantity Quantity of base asset").optional(), + quoteOrderQty: z + .number() + .describe( + `MARKET orders using quoteOrderQty specifies the amount the user wants to spend (when buying) or receive (when selling) the quote asset; the correct quantity will be determined based on the market liquidity and quoteOrderQty. + E.g. Using the symbol BTCUSDT: + BUY side, the order will buy as many BTC as quoteOrderQty USDT can. + SELL side, the order will sell as much BTC needed to receive quoteOrderQty USDT.`, + ) + .optional(), + }, + }, + async ({ symbol, side, quantity, quoteOrderQty }) => { + try { + const result = await spotClient.newOrder(symbol, side as Side, OrderType.MARKET, { + quantity, + quoteOrderQty, + }); + + return { + content: [ + { + type: "text", + text: `Place a new spot TWAP order with Algo service successfully. result: ${JSON.stringify(result)}}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Server failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/binanceTimeWeightedAveragePriceFutureAlgo.ts b/src/tools/binanceTimeWeightedAveragePriceFutureAlgo.ts index 15066269..b717697d 100644 --- a/src/tools/binanceTimeWeightedAveragePriceFutureAlgo.ts +++ b/src/tools/binanceTimeWeightedAveragePriceFutureAlgo.ts @@ -1,48 +1,52 @@ -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; -import { algoClient, spotClient } from "../config/client.js"; - -export function registerBinanceTimeWeightedAveragePriceFutureAlgo(server: McpServer) { - server.tool( - "binanceTimeWeightedAveragePriceFutureAlgo", - `Place a new spot TWAP order with Algo service. Trading for large orders can generate significant selling pressure on the market`, - { - symbol: z.string().describe("symbol: exemple: BTCUSDT"), - side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), - quantity: z.number().describe("quantity Quantity of base asset; Maximum notional per order is 200k, 2mm or 10mm, depending on symbol. Please reduce your size if you order is above the maximum notional per order."), - duration: z.number().describe("duration Duration for TWAP orders in seconds. [300, 86400]"), - }, - async ({ symbol, side, quantity, duration }) => { - try { - - console.log({ symbol, side, quantity, duration }); - - const result = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ - symbol, - side, - quantity, - duration, - }); - - - return { - content: [ - { - type: "text", - text: `Place a new spot TWAP order with Algo service successfully. result: ${JSON.stringify(result)}}`, - }, - ], - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Server failed: ${errorMessage}` }, - ], - isError: true, - }; - } - } - ); -} +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { z } from "zod"; + +import { algoClient } from "../config/client.js"; + +export function registerBinanceTimeWeightedAveragePriceFutureAlgo(server: McpServer) { + server.registerTool( + "binanceTimeWeightedAveragePriceFutureAlgo", + { + description: `Place a new spot TWAP order with Algo service. Trading for large orders can generate significant selling pressure on the market`, + inputSchema: { + symbol: z.string().describe("symbol: exemple: BTCUSDT"), + side: z.enum(["BUY", "SELL"]).describe("BUY or SELL"), + quantity: z + .number() + .describe( + "quantity Quantity of base asset; Maximum notional per order is 200k, 2mm or 10mm, depending on symbol. Please reduce your size if you order is above the maximum notional per order.", + ), + duration: z.number().describe("duration Duration for TWAP orders in seconds. [300, 86400]"), + }, + }, + async ({ symbol, side, quantity, duration }) => { + try { + console.log({ symbol, side, quantity, duration }); + + const result = await algoClient.restAPI.timeWeightedAveragePriceSpotAlgo({ + symbol, + side, + quantity, + duration, + }); + + return { + content: [ + { + type: "text", + text: `Place a new spot TWAP order with Algo service successfully. result: ${JSON.stringify(result)}}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Server failed: ${errorMessage}` }], + isError: true, + }; + } + }, + ); +} diff --git a/src/tools/credit-line/index.ts b/src/tools/credit-line/index.ts index 77ae74d2..84479f7a 100644 --- a/src/tools/credit-line/index.ts +++ b/src/tools/credit-line/index.ts @@ -2,33 +2,36 @@ // Binance.US Credit Line Tools // For institutional clients with credit line agreements -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Binance.US Credit Line tools - * - * ⚠️ IMPORTANT: These APIs require a Credit Line API key type and an institutional + * + * ⚠️ IMPORTANT: These APIs require a Credit Line API key type and an institutional * credit line agreement with Binance.US. These are NOT available to retail users. - * + * * Credit Line allows institutional clients to: * - Borrow assets against collateral * - Trade with borrowed funds * - Manage margin call and liquidation thresholds - * + * * Key metrics: * - LTV (Loan-to-Value): Current loan amount / collateral value * - Margin Call LTV: Threshold that triggers margin call alerts * - Liquidation LTV: Threshold that triggers automatic liquidation */ export function registerCreditLineTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v2/cl/account - Get Credit Line Account Information - // ===================================================================== - server.tool( - "binance_us_cl_account", - `Get current credit line account information including LTV ratios, balances, and loan details. + // ===================================================================== + // GET /sapi/v2/cl/account - Get Credit Line Account Information + // ===================================================================== + server.registerTool( + "binance_us_cl_account", + { + description: `Get current credit line account information including LTV ratios, balances, and loan details. ⚠️ REQUIRES CREDIT LINE API KEY - Standard API keys will not work. ⚠️ Requires institutional credit line agreement with Binance.US. @@ -45,18 +48,19 @@ Returns comprehensive account information including: - availableAmountToTransferOut: How much can be withdrawn - loanAssets: Details of borrowed assets - balances: Current asset balances (collateral)`, - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const requestParams: Record = {}; - if (params.recvWindow) requestParams.recvWindow = params.recvWindow; - - const response = await makeSignedRequest("GET", "/sapi/v2/cl/account", requestParams); - - // Format key metrics for easy reading - const summary = `Credit Line Account Summary: + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const requestParams: Record = {}; + if (params.recvWindow) requestParams.recvWindow = params.recvWindow; + + const response = await makeSignedRequest("GET", "/sapi/v2/cl/account", requestParams); + + // Format key metrics for easy reading + const summary = `Credit Line Account Summary: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Account ID: ${response.clAccountId} Master Account: ${response.masterAccountId} @@ -84,28 +88,32 @@ Contract Period: Required Deposit: ${response.requiredDepositAmount} Available to Withdraw: ${response.availableAmountToTransferOut}`; - return { - content: [{ - type: "text", - text: `${summary}\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get credit line account: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/cl/alert/history - Get Alert History (Margin Calls/Liquidations) - // ===================================================================== - server.tool( - "binance_us_cl_alert_history", - `Get margin call and liquidation alert history for your credit line account. + return { + content: [ + { + type: "text", + text: `${summary}\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get credit line account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/cl/alert/history - Get Alert History (Margin Calls/Liquidations) + // ===================================================================== + server.registerTool( + "binance_us_cl_alert_history", + { + description: `Get margin call and liquidation alert history for your credit line account. ⚠️ REQUIRES CREDIT LINE API KEY - Standard API keys will not work. ⚠️ Requires institutional credit line agreement with Binance.US. @@ -121,59 +129,67 @@ Returns alert records including: Use this to monitor your account's health history and understand when margin calls or liquidation warnings have occurred.`, - { - alertType: z.enum(["MARGIN_CALL", "LIQUIDATION_CALL"]).optional().describe("Filter by alert type"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of results. Default: 200"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const requestParams: Record = {}; - if (params.alertType) requestParams.alertType = params.alertType; - if (params.startTime) requestParams.startTime = params.startTime; - if (params.endTime) requestParams.endTime = params.endTime; - if (params.limit) requestParams.limit = params.limit; - if (params.recvWindow) requestParams.recvWindow = params.recvWindow; - - const response = await makeSignedRequest("GET", "/sapi/v1/cl/alert/history", requestParams); - - // Format alerts for readability - let alertSummary = "Credit Line Alert History:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; - if (Array.isArray(response) && response.length > 0) { - response.forEach((alert: any, index: number) => { - alertSummary += `\n[${index + 1}] ${alert.alertType}\n`; - alertSummary += ` Time: ${new Date(alert.alertTime).toISOString()}\n`; - alertSummary += ` Current LTV: ${(parseFloat(alert.currentLTV) * 100).toFixed(2)}%\n`; - alertSummary += ` Total Balance: $${alert.totalBalance}\n`; - }); - } else { - alertSummary += "No alerts found.\n"; - } - - return { - content: [{ - type: "text", - text: `${alertSummary}\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get alert history: ${errorMessage}` }], - isError: true - }; - } + inputSchema: { + alertType: z + .enum(["MARGIN_CALL", "LIQUIDATION_CALL"]) + .optional() + .describe("Filter by alert type"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of results. Default: 200"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const requestParams: Record = {}; + if (params.alertType) requestParams.alertType = params.alertType; + if (params.startTime) requestParams.startTime = params.startTime; + if (params.endTime) requestParams.endTime = params.endTime; + if (params.limit) requestParams.limit = params.limit; + if (params.recvWindow) requestParams.recvWindow = params.recvWindow; + + const response = await makeSignedRequest("GET", "/sapi/v1/cl/alert/history", requestParams); + + // Format alerts for readability + let alertSummary = "Credit Line Alert History:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; + if (Array.isArray(response) && response.length > 0) { + response.forEach((alert: any, index: number) => { + alertSummary += `\n[${index + 1}] ${alert.alertType}\n`; + alertSummary += ` Time: ${new Date(alert.alertTime).toISOString()}\n`; + alertSummary += ` Current LTV: ${(parseFloat(alert.currentLTV) * 100).toFixed(2)}%\n`; + alertSummary += ` Total Balance: $${alert.totalBalance}\n`; + }); + } else { + alertSummary += "No alerts found.\n"; } - ); - // ===================================================================== - // GET /sapi/v1/cl/transferHistory - Get Transfer History - // ===================================================================== - server.tool( - "binance_us_cl_transfer_history", - `Get transfer history for your credit line account. + return { + content: [ + { + type: "text", + text: `${alertSummary}\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get alert history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/cl/transferHistory - Get Transfer History + // ===================================================================== + server.registerTool( + "binance_us_cl_transfer_history", + { + description: `Get transfer history for your credit line account. ⚠️ REQUIRES CREDIT LINE API KEY - Standard API keys will not work. ⚠️ Requires institutional credit line agreement with Binance.US. @@ -187,62 +203,74 @@ Returns transfer records including: - transferTime: When the transfer occurred Use this to track deposits and withdrawals from your credit line account.`, - { - transferType: z.enum(["TRANSFER_IN", "TRANSFER_OUT"]).optional().describe("Filter by transfer type"), - asset: z.string().optional().describe("Filter by asset, e.g., BTC, USD"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of results. Default: 20, Max: 100"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const requestParams: Record = {}; - if (params.transferType) requestParams.transferType = params.transferType; - if (params.asset) requestParams.asset = params.asset.toUpperCase(); - if (params.startTime) requestParams.startTime = params.startTime; - if (params.endTime) requestParams.endTime = params.endTime; - if (params.limit) requestParams.limit = params.limit; - if (params.recvWindow) requestParams.recvWindow = params.recvWindow; - - const response = await makeSignedRequest("GET", "/sapi/v1/cl/transferHistory", requestParams); - - // Format transfers for readability - let transferSummary = "Credit Line Transfer History:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; - if (Array.isArray(response) && response.length > 0) { - response.forEach((transfer: any, index: number) => { - const direction = transfer.transferType === "TRANSFER_IN" ? "→ IN" : "← OUT"; - transferSummary += `\n[${index + 1}] ${direction} ${transfer.amount} ${transfer.asset}\n`; - transferSummary += ` ID: ${transfer.transferId}\n`; - transferSummary += ` Status: ${transfer.status}\n`; - transferSummary += ` Time: ${new Date(transfer.transferTime).toISOString()}\n`; - }); - } else { - transferSummary += "No transfers found.\n"; - } - - return { - content: [{ - type: "text", - text: `${transferSummary}\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], - isError: true - }; - } + inputSchema: { + transferType: z + .enum(["TRANSFER_IN", "TRANSFER_OUT"]) + .optional() + .describe("Filter by transfer type"), + asset: z.string().optional().describe("Filter by asset, e.g., BTC, USD"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of results. Default: 20, Max: 100"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const requestParams: Record = {}; + if (params.transferType) requestParams.transferType = params.transferType; + if (params.asset) requestParams.asset = params.asset.toUpperCase(); + if (params.startTime) requestParams.startTime = params.startTime; + if (params.endTime) requestParams.endTime = params.endTime; + if (params.limit) requestParams.limit = params.limit; + if (params.recvWindow) requestParams.recvWindow = params.recvWindow; + + const response = await makeSignedRequest( + "GET", + "/sapi/v1/cl/transferHistory", + requestParams, + ); + + // Format transfers for readability + let transferSummary = "Credit Line Transfer History:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; + if (Array.isArray(response) && response.length > 0) { + response.forEach((transfer: any, index: number) => { + const direction = transfer.transferType === "TRANSFER_IN" ? "→ IN" : "← OUT"; + transferSummary += `\n[${index + 1}] ${direction} ${transfer.amount} ${transfer.asset}\n`; + transferSummary += ` ID: ${transfer.transferId}\n`; + transferSummary += ` Status: ${transfer.status}\n`; + transferSummary += ` Time: ${new Date(transfer.transferTime).toISOString()}\n`; + }); + } else { + transferSummary += "No transfers found.\n"; } - ); - // ===================================================================== - // POST /sapi/v1/cl/transfer - Execute Transfer - // ===================================================================== - server.tool( - "binance_us_cl_transfer", - `Transfer assets in or out of your credit line account. + return { + content: [ + { + type: "text", + text: `${transferSummary}\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/cl/transfer - Execute Transfer + // ===================================================================== + server.registerTool( + "binance_us_cl_transfer", + { + description: `Transfer assets in or out of your credit line account. ⚠️ REQUIRES CREDIT LINE API KEY - Standard API keys will not work. ⚠️ Requires institutional credit line agreement with Binance.US. @@ -254,38 +282,44 @@ Transfer types: Note: Transferring out may be restricted if it would cause LTV to exceed limits. Check availableAmountToTransferOut in binance_us_cl_account first.`, - { - transferType: z.enum(["TRANSFER_IN", "TRANSFER_OUT"]).describe("Direction: TRANSFER_IN (deposit) or TRANSFER_OUT (withdraw)"), - transferAssetType: z.string().describe("Asset to transfer, e.g., BTC, USD"), - quantity: z.number().positive().describe("Amount to transfer"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000") - }, - async (params) => { - try { - const requestParams: Record = { - transferType: params.transferType, - transferAssetType: params.transferAssetType.toUpperCase(), - quantity: params.quantity - }; - if (params.recvWindow) requestParams.recvWindow = params.recvWindow; - - const response = await makeSignedRequest("POST", "/sapi/v1/cl/transfer", requestParams); - - const direction = params.transferType === "TRANSFER_IN" ? "deposited to" : "withdrawn from"; - - return { - content: [{ - type: "text", - text: `Transfer completed!\n\nTransfer ID: ${response.transferId}\nStatus: ${response.status}\n${params.quantity} ${params.transferAssetType.toUpperCase()} ${direction} credit line account.\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + transferType: z + .enum(["TRANSFER_IN", "TRANSFER_OUT"]) + .describe("Direction: TRANSFER_IN (deposit) or TRANSFER_OUT (withdraw)"), + transferAssetType: z.string().describe("Asset to transfer, e.g., BTC, USD"), + quantity: z.number().positive().describe("Amount to transfer"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async (params) => { + try { + const requestParams: Record = { + transferType: params.transferType, + transferAssetType: params.transferAssetType.toUpperCase(), + quantity: params.quantity, + }; + if (params.recvWindow) requestParams.recvWindow = params.recvWindow; + + const response = await makeSignedRequest("POST", "/sapi/v1/cl/transfer", requestParams); + + const direction = params.transferType === "TRANSFER_IN" ? "deposited to" : "withdrawn from"; + + return { + content: [ + { + type: "text", + text: `Transfer completed!\n\nTransfer ID: ${response.transferId}\nStatus: ${response.status}\n${params.quantity} ${params.transferAssetType.toUpperCase()} ${direction} credit line account.\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/creditline/index.ts b/src/tools/creditline/index.ts index ef917b95..3a3a0566 100644 --- a/src/tools/creditline/index.ts +++ b/src/tools/creditline/index.ts @@ -2,28 +2,31 @@ // Binance.US Credit Line Tools // For institutional credit line agreements -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Binance.US Credit Line tools - * + * * ⚠️ IMPORTANT: These APIs require a Credit Line agreement with Binance.US. * They are only available to institutional users with approved credit facilities. * Standard Binance.US accounts do NOT have access to these endpoints. - * + * * Credit Line allows institutional traders to trade with borrowed funds, * similar to margin trading but with different risk parameters and * institutional-grade features. */ export function registerCreditLineTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v2/cl/account - Get Credit Line Account Information - // ===================================================================== - server.tool( - "binance_us_cl_account", - `Get comprehensive credit line account information. + // ===================================================================== + // GET /sapi/v2/cl/account - Get Credit Line Account Information + // ===================================================================== + server.registerTool( + "binance_us_cl_account", + { + description: `Get comprehensive credit line account information. ⚠️ REQUIRES INSTITUTIONAL CREDIT LINE AGREEMENT This API is only available to institutional users with approved credit facilities. @@ -58,33 +61,42 @@ Loan Information: Balances: - balances: Array of asset balances (free, locked)`, - { - recvWindow: z.number().int().max(60000).optional().describe("Request validity window in ms (max: 60000)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v2/cl/account", { - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - // Calculate risk level based on LTV - let riskLevel = "LOW"; - const currentLTV = parseFloat(response.currentLTV); - const marginCallLTV = parseFloat(response.marginCallLTV); - const liquidationLTV = parseFloat(response.liquidationLTV); - - if (currentLTV >= liquidationLTV) { - riskLevel = "CRITICAL - LIQUIDATION IMMINENT"; - } else if (currentLTV >= marginCallLTV) { - riskLevel = "HIGH - MARGIN CALL"; - } else if (currentLTV >= marginCallLTV * 0.9) { - riskLevel = "MEDIUM"; - } - - return { - content: [{ - type: "text", - text: `Credit Line Account Info retrieved. + inputSchema: { + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Request validity window in ms (max: 60000)"), + }, + }, + async (params: Record) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v2/cl/account", { + ...(params.recvWindow != null && { + recvWindow: params.recvWindow as number, + }), + }); + + // Calculate risk level based on LTV + let riskLevel = "LOW"; + const currentLTV = parseFloat(response.currentLTV); + const marginCallLTV = parseFloat(response.marginCallLTV); + const liquidationLTV = parseFloat(response.liquidationLTV); + + if (currentLTV >= liquidationLTV) { + riskLevel = "CRITICAL - LIQUIDATION IMMINENT"; + } else if (currentLTV >= marginCallLTV) { + riskLevel = "HIGH - MARGIN CALL"; + } else if (currentLTV >= marginCallLTV * 0.9) { + riskLevel = "MEDIUM"; + } + + return { + content: [ + { + type: "text", + text: `Credit Line Account Info retrieved. ⚠️ Risk Level: ${riskLevel} 📊 Current LTV: ${(currentLTV * 100).toFixed(2)}% @@ -92,25 +104,28 @@ Balances: 🔴 Liquidation LTV: ${(liquidationLTV * 100).toFixed(2)}% 💰 Interest Rate: ${(parseFloat(response.interestRate) * 100).toFixed(2)}% annual -Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get credit line account: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/cl/alert/history - Get Alert History (Margin Call & Liquidation) - // ===================================================================== - server.tool( - "binance_us_cl_alert_history", - `Get margin call and liquidation alert history for credit line account. +Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get credit line account: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/cl/alert/history - Get Alert History (Margin Call & Liquidation) + // ===================================================================== + server.registerTool( + "binance_us_cl_alert_history", + { + description: `Get margin call and liquidation alert history for credit line account. ⚠️ REQUIRES INSTITUTIONAL CREDIT LINE AGREEMENT @@ -131,55 +146,77 @@ Use this to: - Review past risk events - Understand account risk patterns - Audit margin call history`, - { - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().min(1).max(1000).optional().default(200).describe("Max records (default: 200)"), - alertType: z.enum(["LIQUIDATION_CALL", "MARGIN_CALL"]).optional().describe("Filter by alert type"), - recvWindow: z.number().int().max(60000).optional().describe("Request validity window (max: 60000)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/cl/alert/history", { - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.alertType && { alertType: params.alertType }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const alerts = Array.isArray(response) ? response : []; - const marginCalls = alerts.filter((a: any) => a.alertType === "MARGIN_CALL").length; - const liquidationCalls = alerts.filter((a: any) => a.alertType === "LIQUIDATION_CALL").length; - - return { - content: [{ - type: "text", - text: `Credit Line Alert History retrieved. + inputSchema: { + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .default(200) + .describe("Max records (default: 200)"), + alertType: z + .enum(["LIQUIDATION_CALL", "MARGIN_CALL"]) + .optional() + .describe("Filter by alert type"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Request validity window (max: 60000)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/cl/alert/history", { + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.alertType && { alertType: params.alertType }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const alerts = Array.isArray(response) ? response : []; + const marginCalls = alerts.filter((a: any) => a.alertType === "MARGIN_CALL").length; + const liquidationCalls = alerts.filter( + (a: any) => a.alertType === "LIQUIDATION_CALL", + ).length; + + return { + content: [ + { + type: "text", + text: `Credit Line Alert History retrieved. 📊 Total Alerts: ${alerts.length} ⚠️ Margin Calls: ${marginCalls} 🔴 Liquidation Calls: ${liquidationCalls} -Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get alert history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/cl/transferHistory - Get Transfer History - // ===================================================================== - server.tool( - "binance_us_cl_transfer_history", - `Get transfer history for credit line account. +Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get alert history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/cl/transferHistory - Get Transfer History + // ===================================================================== + server.registerTool( + "binance_us_cl_transfer_history", + { + description: `Get transfer history for credit line account. ⚠️ REQUIRES INSTITUTIONAL CREDIT LINE AGREEMENT @@ -199,57 +236,77 @@ Use this to: - Track collateral movements - Audit deposit/withdrawal history - Reconcile account activity`, - { - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().min(1).max(100).optional().default(20).describe("Max records (default: 20, max: 100)"), - transferType: z.enum(["TRANSFER_IN", "TRANSFER_OUT"]).optional().describe("Filter by transfer direction"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC, USD)"), - recvWindow: z.number().int().max(60000).optional().describe("Request validity window (max: 60000)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/cl/transferHistory", { - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.transferType && { transferType: params.transferType }), - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const transfers = Array.isArray(response) ? response : []; - const transfersIn = transfers.filter((t: any) => t.transferType === "TRANSFER_IN").length; - const transfersOut = transfers.filter((t: any) => t.transferType === "TRANSFER_OUT").length; - - return { - content: [{ - type: "text", - text: `Credit Line Transfer History retrieved. + inputSchema: { + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .default(20) + .describe("Max records (default: 20, max: 100)"), + transferType: z + .enum(["TRANSFER_IN", "TRANSFER_OUT"]) + .optional() + .describe("Filter by transfer direction"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC, USD)"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Request validity window (max: 60000)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/cl/transferHistory", { + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.transferType && { transferType: params.transferType }), + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const transfers = Array.isArray(response) ? response : []; + const transfersIn = transfers.filter((t: any) => t.transferType === "TRANSFER_IN").length; + const transfersOut = transfers.filter((t: any) => t.transferType === "TRANSFER_OUT").length; + + return { + content: [ + { + type: "text", + text: `Credit Line Transfer History retrieved. 📊 Total Transfers: ${transfers.length} 📥 Transfers In: ${transfersIn} 📤 Transfers Out: ${transfersOut} -Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/cl/transfer - Execute Transfer - // ===================================================================== - server.tool( - "binance_us_cl_transfer", - `Execute a transfer in or out of the credit line account. +Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/cl/transfer - Execute Transfer + // ===================================================================== + server.registerTool( + "binance_us_cl_transfer", + { + description: `Execute a transfer in or out of the credit line account. ⚠️ REQUIRES INSTITUTIONAL CREDIT LINE AGREEMENT @@ -269,29 +326,37 @@ Transfer Types: Response includes: - transferId: Unique transfer identifier - status: SUCCESS, PENDING, or FAILED`, - { - transferType: z.enum(["TRANSFER_IN", "TRANSFER_OUT"]).describe("Direction: TRANSFER_IN (deposit) or TRANSFER_OUT (withdraw)"), - transferAssetType: z.string().describe("Asset to transfer (e.g., BTC, USD)"), - quantity: z.number().positive().describe("Amount to transfer"), - recvWindow: z.number().int().max(60000).optional().describe("Request validity window (max: 60000)") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/cl/transfer", { - transferType: params.transferType, - transferAssetType: params.transferAssetType.toUpperCase(), - quantity: params.quantity, - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const actionText = params.transferType === "TRANSFER_IN" - ? "deposited into" - : "withdrawn from"; - - return { - content: [{ - type: "text", - text: `Credit Line Transfer executed. + inputSchema: { + transferType: z + .enum(["TRANSFER_IN", "TRANSFER_OUT"]) + .describe("Direction: TRANSFER_IN (deposit) or TRANSFER_OUT (withdraw)"), + transferAssetType: z.string().describe("Asset to transfer (e.g., BTC, USD)"), + quantity: z.number().positive().describe("Amount to transfer"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Request validity window (max: 60000)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/cl/transfer", { + transferType: params.transferType, + transferAssetType: params.transferAssetType.toUpperCase(), + quantity: params.quantity, + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const actionText = + params.transferType === "TRANSFER_IN" ? "deposited into" : "withdrawn from"; + + return { + content: [ + { + type: "text", + text: `Credit Line Transfer executed. ${params.transferType === "TRANSFER_OUT" ? "⚠️ Your LTV ratio has increased. Monitor your position." : "✅ Collateral added. Your LTV ratio has decreased."} @@ -299,25 +364,28 @@ ${params.transferType === "TRANSFER_OUT" ? "⚠️ Your LTV ratio has increased. 📋 Transfer ID: ${response.transferId} ✅ Status: ${response.status} -Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/cl/liquidation/history - Get Liquidation History - // ===================================================================== - server.tool( - "binance_us_cl_liquidation_history", - `Get liquidation history for credit line account. +Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/cl/liquidation/history - Get Liquidation History + // ===================================================================== + server.registerTool( + "binance_us_cl_liquidation_history", + { + description: `Get liquidation history for credit line account. ⚠️ REQUIRES INSTITUTIONAL CREDIT LINE AGREEMENT @@ -334,41 +402,57 @@ Use this to: - Review past liquidation events - Understand liquidation patterns - Audit risk management effectiveness`, - { - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - limit: z.number().int().min(1).max(100).optional().default(20).describe("Max records (default: 20, max: 100)"), - recvWindow: z.number().int().max(60000).optional().describe("Request validity window (max: 60000)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/cl/liquidation/history", { - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.recvWindow && { recvWindow: params.recvWindow }) - }); - - const liquidations = Array.isArray(response) ? response : []; - - return { - content: [{ - type: "text", - text: `Credit Line Liquidation History retrieved. + inputSchema: { + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .default(20) + .describe("Max records (default: 20, max: 100)"), + recvWindow: z + .number() + .int() + .max(60000) + .optional() + .describe("Request validity window (max: 60000)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/cl/liquidation/history", { + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.recvWindow && { recvWindow: params.recvWindow }), + }); + + const liquidations = Array.isArray(response) ? response : []; + + return { + content: [ + { + type: "text", + text: `Credit Line Liquidation History retrieved. 🔴 Total Liquidations: ${liquidations.length} ${liquidations.length > 0 ? "⚠️ Review your risk management strategy." : "✅ No liquidation events found."} -Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get liquidation history: ${errorMessage}` }], - isError: true - }; - } - } - ); +Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get liquidation history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/custodial-solution/index.ts b/src/tools/custodial-solution/index.ts index 101d1252..fa4dde93 100644 --- a/src/tools/custodial-solution/index.ts +++ b/src/tools/custodial-solution/index.ts @@ -3,31 +3,34 @@ // ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY - Not available to regular users // Only for users with a Custody Exchange Network agreement -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Binance.US Custodial Solution tools - * + * * ⚠️ IMPORTANT: These endpoints require a Custodial Solution API Key * Regular Exchange API Keys will NOT work with these endpoints. - * + * * Custodial Solution API is for institutional users who have entered into * a Custody Exchange Network agreement with a participating custody partner. - * + * * Categories: * - User Account Data (balance, supported assets) * - Transfer (wallet transfer, custodian transfer, undo transfer) * - Settlement (to custodial partner) */ export function registerCustodialSolutionTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v1/custodian/balance - Get Account Balance - // ===================================================================== - server.tool( - "binance_us_custodial_balance", - `Get balance information for Binance.US exchange wallet and custodial sub-account. + // ===================================================================== + // GET /sapi/v1/custodian/balance - Get Account Balance + // ===================================================================== + server.registerTool( + "binance_us_custodial_balance", + { + description: `Get balance information for Binance.US exchange wallet and custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY - Regular API keys will not work. @@ -41,37 +44,45 @@ Each balance includes: - locked: Locked balance (in orders, etc.) - inSettlement: Amount in settlement process (custodial only) - lastUpdatedTime: Last update timestamp`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase, e.g., 'FIREBLOCKS')") - }, - async ({ rail }) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/balance", { - rail: rail.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `Custodial Balance Information:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get custodial balance: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/supportedAssetList - Get Supported Assets - // ===================================================================== - server.tool( - "binance_us_custodial_supported_assets", - `Get list of assets supported for custodial transfers and settlements. + inputSchema: { + rail: z + .string() + .describe("Custodial partner identifier (all uppercase, e.g., 'FIREBLOCKS')"), + }, + }, + async (params: { rail: string }) => { + const { rail } = params; + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/balance", { + rail: rail.toUpperCase(), + }); + + return { + content: [ + { + type: "text", + text: `Custodial Balance Information:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get custodial balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/supportedAssetList - Get Supported Assets + // ===================================================================== + server.registerTool( + "binance_us_custodial_supported_assets", + { + description: `Get list of assets supported for custodial transfers and settlements. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -83,350 +94,441 @@ Each asset includes: - asset: Asset symbol - precision: Decimal precision - network: Supported networks for the asset`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)") - }, - async ({ rail }) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/supportedAssetList", { - rail: rail.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `Custodial Supported Assets:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get supported assets: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/walletTransfer - Transfer From Exchange Wallet - // ===================================================================== - server.tool( - "binance_us_custodial_wallet_transfer", - `Transfer assets from your Binance.US exchange wallet to your custodial sub-account. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + }, + }, + async (params: { rail: string }) => { + const { rail } = params; + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/supportedAssetList", { + rail: rail.toUpperCase(), + }); + + return { + content: [ + { + type: "text", + text: `Custodial Supported Assets:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get supported assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/walletTransfer - Transfer From Exchange Wallet + // ===================================================================== + server.registerTool( + "binance_us_custodial_wallet_transfer", + { + description: `Transfer assets from your Binance.US exchange wallet to your custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY ⚠️ This moves funds - verify details carefully! This transfers from your main Binance.US account to your custodial sub-account, which can then be traded or settled to your custodial partner.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), - amount: z.number().positive().describe("Amount to transfer"), - clientOrderId: z.string().optional().describe("Your reference ID (auto-generated if not provided)") - }, - async ({ rail, asset, amount, clientOrderId }) => { - try { - const params: Record = { - rail: rail.toUpperCase(), - asset: asset.toUpperCase(), - amount - }; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/walletTransfer", params); - - return { - content: [{ - type: "text", - text: `Wallet Transfer Submitted!\n\nTransfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute wallet transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/custodianTransfer - Transfer From Custodian - // ===================================================================== - server.tool( - "binance_us_custodial_custodian_transfer", - `Request asset transfer from a custodial partner account to Binance.US custodial sub-account. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), + amount: z.number().positive().describe("Amount to transfer"), + clientOrderId: z + .string() + .optional() + .describe("Your reference ID (auto-generated if not provided)"), + }, + }, + async ({ rail, asset, amount, clientOrderId }) => { + try { + const params: Record = { + rail: rail.toUpperCase(), + asset: asset.toUpperCase(), + amount, + }; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const response = await makeSignedRequest( + "POST", + "/sapi/v1/custodian/walletTransfer", + params, + ); + + return { + content: [ + { + type: "text", + text: `Wallet Transfer Submitted!\n\nTransfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to execute wallet transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/custodianTransfer - Transfer From Custodian + // ===================================================================== + server.registerTool( + "binance_us_custodial_custodian_transfer", + { + description: `Request asset transfer from a custodial partner account to Binance.US custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY ⚠️ This initiates a transfer request to your custody partner! This requests your custodial partner to transfer assets to your Binance.US account. The actual transfer is executed by the custody partner.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), - amount: z.number().positive().describe("Amount to transfer"), - clientOrderId: z.string().optional().describe("Your reference ID (auto-generated if not provided)") - }, - async ({ rail, asset, amount, clientOrderId }) => { - try { - const params: Record = { - rail: rail.toUpperCase(), - asset: asset.toUpperCase(), - amount - }; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/custodianTransfer", params); - - return { - content: [{ - type: "text", - text: `Custodian Transfer Requested!\n\nTransfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to request custodian transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/undoTransfer - Undo Transfer - // ===================================================================== - server.tool( - "binance_us_custodial_undo_transfer", - `Undo a previous transfer from your custodial partner. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), + amount: z.number().positive().describe("Amount to transfer"), + clientOrderId: z + .string() + .optional() + .describe("Your reference ID (auto-generated if not provided)"), + }, + }, + async ({ rail, asset, amount, clientOrderId }) => { + try { + const params: Record = { + rail: rail.toUpperCase(), + asset: asset.toUpperCase(), + amount, + }; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const response = await makeSignedRequest( + "POST", + "/sapi/v1/custodian/custodianTransfer", + params, + ); + + return { + content: [ + { + type: "text", + text: `Custodian Transfer Requested!\n\nTransfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to request custodian transfer: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/undoTransfer - Undo Transfer + // ===================================================================== + server.registerTool( + "binance_us_custodial_undo_transfer", + { + description: `Undo a previous transfer from your custodial partner. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY ⚠️ Only certain transfers can be undone - check with your custodial partner. This reverses a previous custodian transfer by its transfer ID.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - originTransferId: z.string().describe("The transfer ID of the original transfer to undo") - }, - async ({ rail, originTransferId }) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/undoTransfer", { - rail: rail.toUpperCase(), - originTransferId - }); - - return { - content: [{ - type: "text", - text: `Transfer Undone!\n\nUndo Transfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to undo transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/walletTransferHistory - Wallet Transfer History - // ===================================================================== - server.tool( - "binance_us_custodial_wallet_transfer_history", - `Get history of transfers from Binance.US exchange wallet to custodial sub-account. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + originTransferId: z.string().describe("The transfer ID of the original transfer to undo"), + }, + }, + async ({ rail, originTransferId }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/undoTransfer", { + rail: rail.toUpperCase(), + originTransferId, + }); + + return { + content: [ + { + type: "text", + text: `Transfer Undone!\n\nUndo Transfer ID: ${response.transferId}\nAsset: ${response.asset}\nAmount: ${response.amount}\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to undo transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/walletTransferHistory - Wallet Transfer History + // ===================================================================== + server.registerTool( + "binance_us_custodial_wallet_transfer_history", + { + description: `Get history of transfers from Binance.US exchange wallet to custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Returns transfer history with status, amounts, and timestamps.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - transferId: z.string().optional().describe("Filter by specific transfer ID"), - clientOrderId: z.string().optional().describe("Filter by your reference ID"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds (default: 90 days ago)"), - endTime: z.number().optional().describe("End time in milliseconds (default: now)"), - page: z.number().optional().describe("Page number (default: 1)"), - limit: z.number().optional().describe("Results per page (default: 20, max: 100)") - }, - async ({ rail, transferId, clientOrderId, asset, startTime, endTime, page, limit }) => { - try { - const params: Record = { rail: rail.toUpperCase() }; - if (transferId) params.transferId = transferId; - if (clientOrderId) params.clientOrderId = clientOrderId; - if (asset) params.asset = asset.toUpperCase(); - if (startTime) params.startTime = startTime; - if (endTime) params.endTime = endTime; - if (page) params.page = page; - if (limit) params.limit = limit; - - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/walletTransferHistory", params); - - return { - content: [{ - type: "text", - text: `Wallet Transfer History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get wallet transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/custodianTransferHistory - Custodian Transfer History - // ===================================================================== - server.tool( - "binance_us_custodial_custodian_transfer_history", - `Get history of transfers from custodial partner, including ExpressTrade and Undo transfers. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + transferId: z.string().optional().describe("Filter by specific transfer ID"), + clientOrderId: z.string().optional().describe("Filter by your reference ID"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), + startTime: z + .number() + .optional() + .describe("Start time in milliseconds (default: 90 days ago)"), + endTime: z.number().optional().describe("End time in milliseconds (default: now)"), + page: z.number().optional().describe("Page number (default: 1)"), + limit: z.number().optional().describe("Results per page (default: 20, max: 100)"), + }, + }, + async ({ rail, transferId, clientOrderId, asset, startTime, endTime, page, limit }) => { + try { + const params: Record = { rail: rail.toUpperCase() }; + if (transferId) params.transferId = transferId; + if (clientOrderId) params.clientOrderId = clientOrderId; + if (asset) params.asset = asset.toUpperCase(); + if (startTime) params.startTime = startTime; + if (endTime) params.endTime = endTime; + if (page) params.page = page; + if (limit) params.limit = limit; + + const response = await makeSignedRequest( + "GET", + "/sapi/v1/custodian/walletTransferHistory", + params, + ); + + return { + content: [ + { + type: "text", + text: `Wallet Transfer History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get wallet transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/custodianTransferHistory - Custodian Transfer History + // ===================================================================== + server.registerTool( + "binance_us_custodial_custodian_transfer_history", + { + description: `Get history of transfers from custodial partner, including ExpressTrade and Undo transfers. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Returns transfer history with status, amounts, and timestamps.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - transferId: z.string().optional().describe("Filter by specific transfer ID"), - clientOrderId: z.string().optional().describe("Filter by your reference ID"), - expressTradeTransfer: z.boolean().optional().describe("Filter by ExpressTrade transfers only"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number (default: 1)"), - limit: z.number().optional().describe("Results per page (default: 20, max: 100)") - }, - async ({ rail, transferId, clientOrderId, expressTradeTransfer, asset, startTime, endTime, page, limit }) => { - try { - const params: Record = { rail: rail.toUpperCase() }; - if (transferId) params.transferId = transferId; - if (clientOrderId) params.clientOrderId = clientOrderId; - if (expressTradeTransfer !== undefined) params.expressTradeTransfer = expressTradeTransfer; - if (asset) params.asset = asset.toUpperCase(); - if (startTime) params.startTime = startTime; - if (endTime) params.endTime = endTime; - if (page) params.page = page; - if (limit) params.limit = limit; - - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/custodianTransferHistory", params); - - return { - content: [{ - type: "text", - text: `Custodian Transfer History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get custodian transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/settlement - Request Settlement - // ===================================================================== - server.tool( - "binance_us_custodial_settlement", - `Request settlement of assets from custodial sub-account to custodial partner. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + transferId: z.string().optional().describe("Filter by specific transfer ID"), + clientOrderId: z.string().optional().describe("Filter by your reference ID"), + expressTradeTransfer: z + .boolean() + .optional() + .describe("Filter by ExpressTrade transfers only"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number (default: 1)"), + limit: z.number().optional().describe("Results per page (default: 20, max: 100)"), + }, + }, + async ({ + rail, + transferId, + clientOrderId, + expressTradeTransfer, + asset, + startTime, + endTime, + page, + limit, + }) => { + try { + const params: Record = { rail: rail.toUpperCase() }; + if (transferId) params.transferId = transferId; + if (clientOrderId) params.clientOrderId = clientOrderId; + if (expressTradeTransfer !== undefined) params.expressTradeTransfer = expressTradeTransfer; + if (asset) params.asset = asset.toUpperCase(); + if (startTime) params.startTime = startTime; + if (endTime) params.endTime = endTime; + if (page) params.page = page; + if (limit) params.limit = limit; + + const response = await makeSignedRequest( + "GET", + "/sapi/v1/custodian/custodianTransferHistory", + params, + ); + + return { + content: [ + { + type: "text", + text: `Custodian Transfer History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get custodian transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/settlement - Request Settlement + // ===================================================================== + server.registerTool( + "binance_us_custodial_settlement", + { + description: `Request settlement of assets from custodial sub-account to custodial partner. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY ⚠️ This sends funds to your custodial partner! This settles (withdraws) assets from your Binance.US custodial sub-account to your custody partner's vault.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - asset: z.string().describe("Asset to settle (e.g., BTC, ETH)"), - amount: z.number().positive().describe("Amount to settle"), - clientOrderId: z.string().optional().describe("Your reference ID (auto-generated if not provided)") - }, - async ({ rail, asset, amount, clientOrderId }) => { - try { - const params: Record = { - rail: rail.toUpperCase(), - asset: asset.toUpperCase(), - amount - }; - if (clientOrderId) params.clientOrderId = clientOrderId; - - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/settlement", params); - - return { - content: [{ - type: "text", - text: `Settlement Requested!\n\nSettlement ID: ${response.settlementId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to request settlement: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/settlementHistory - Settlement History - // ===================================================================== - server.tool( - "binance_us_custodial_settlement_history", - `Get history of settlements from custodial sub-account to custodial partner. + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + asset: z.string().describe("Asset to settle (e.g., BTC, ETH)"), + amount: z.number().positive().describe("Amount to settle"), + clientOrderId: z + .string() + .optional() + .describe("Your reference ID (auto-generated if not provided)"), + }, + }, + async ({ rail, asset, amount, clientOrderId }) => { + try { + const params: Record = { + rail: rail.toUpperCase(), + asset: asset.toUpperCase(), + amount, + }; + if (clientOrderId) params.clientOrderId = clientOrderId; + + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/settlement", params); + + return { + content: [ + { + type: "text", + text: `Settlement Requested!\n\nSettlement ID: ${response.settlementId}\nAsset: ${response.asset}\nAmount: ${response.amount}\nStatus: ${response.status}\n\nFull Response:\n${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to request settlement: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/settlementHistory - Settlement History + // ===================================================================== + server.registerTool( + "binance_us_custodial_settlement_history", + { + description: `Get history of settlements from custodial sub-account to custodial partner. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Returns settlement history with status, amounts, and timestamps.`, - { - rail: z.string().describe("Custodial partner identifier (all uppercase)"), - settlementId: z.string().optional().describe("Filter by specific settlement ID"), - clientOrderId: z.string().optional().describe("Filter by your reference ID"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number (default: 1)"), - limit: z.number().optional().describe("Results per page (default: 20, max: 100)") - }, - async ({ rail, settlementId, clientOrderId, asset, startTime, endTime, page, limit }) => { - try { - const params: Record = { rail: rail.toUpperCase() }; - if (settlementId) params.settlementId = settlementId; - if (clientOrderId) params.clientOrderId = clientOrderId; - if (asset) params.asset = asset.toUpperCase(); - if (startTime) params.startTime = startTime; - if (endTime) params.endTime = endTime; - if (page) params.page = page; - if (limit) params.limit = limit; - - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/settlementHistory", params); - - return { - content: [{ - type: "text", - text: `Settlement History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get settlement history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + rail: z.string().describe("Custodial partner identifier (all uppercase)"), + settlementId: z.string().optional().describe("Filter by specific settlement ID"), + clientOrderId: z.string().optional().describe("Filter by your reference ID"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number (default: 1)"), + limit: z.number().optional().describe("Results per page (default: 20, max: 100)"), + }, + }, + async ({ rail, settlementId, clientOrderId, asset, startTime, endTime, page, limit }) => { + try { + const params: Record = { rail: rail.toUpperCase() }; + if (settlementId) params.settlementId = settlementId; + if (clientOrderId) params.clientOrderId = clientOrderId; + if (asset) params.asset = asset.toUpperCase(); + if (startTime) params.startTime = startTime; + if (endTime) params.endTime = endTime; + if (page) params.page = page; + if (limit) params.limit = limit; + + const response = await makeSignedRequest( + "GET", + "/sapi/v1/custodian/settlementHistory", + params, + ); + + return { + content: [ + { + type: "text", + text: `Settlement History:\n\nTotal: ${response.total}\n\n${JSON.stringify(response.data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get settlement history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/custodial/index.ts b/src/tools/custodial/index.ts index 3115c856..f3f6db9c 100644 --- a/src/tools/custodial/index.ts +++ b/src/tools/custodial/index.ts @@ -2,22 +2,26 @@ // Binance.US Custodial Solution Tools // For institutional custody partners (e.g., Anchorage, BitGo) -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; // Common schema for rail parameter (custodial partner) -const railSchema = z.string().describe("Custodial partner name (e.g., ANCHORAGE, BITGO). Must be uppercase."); +const railSchema = z + .string() + .describe("Custodial partner name (e.g., ANCHORAGE, BITGO). Must be uppercase."); // Order type enum const orderTypeEnum = z.enum([ - "LIMIT", - "MARKET", - "STOP_LOSS", - "STOP_LOSS_LIMIT", - "TAKE_PROFIT", - "TAKE_PROFIT_LIMIT", - "LIMIT_MAKER" + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", ]); // Order side enum @@ -28,21 +32,22 @@ const timeInForceEnum = z.enum(["GTC", "IOC", "FOK"]); /** * Register all Binance.US Custodial Solution tools - * + * * ⚠️ IMPORTANT: These APIs require a special Custodial Solution API key type. * Standard Binance.US API keys will NOT work with these endpoints. - * + * * Custodial Solution is designed for institutional custody partners like * Anchorage, allowing them to trade on behalf of their clients while * maintaining custody of the assets. */ export function registerCustodialTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v1/custodian/balance - Get Custodial Account Balance - // ===================================================================== - server.tool( - "binance_us_cust_balance", - `Get balance information for Binance.US exchange wallet and custodial sub-account. + // ===================================================================== + // GET /sapi/v1/custodian/balance - Get Custodial Account Balance + // ===================================================================== + server.registerTool( + "binance_us_cust_balance", + { + description: `Get balance information for Binance.US exchange wallet and custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY - Standard API keys will not work. @@ -58,37 +63,42 @@ Each balance entry contains: - locked: Locked balance - inSettlement: Amount in settlement (custodial only) - lastUpdatedTime: Last update timestamp`, - { - rail: railSchema - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/balance", { - rail: params.rail.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved custodial balance. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get custodial balance: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/supportedAssetList - Get Supported Assets - // ===================================================================== - server.tool( - "binance_us_cust_supported_assets", - `Get list of assets supported for custodial solution transfers and settlements. + inputSchema: { + rail: railSchema, + }, + }, + async (params: { rail: string }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/balance", { + rail: params.rail.toUpperCase(), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved custodial balance. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get custodial balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/supportedAssetList - Get Supported Assets + // ===================================================================== + server.registerTool( + "binance_us_cust_supported_assets", + { + description: `Get list of assets supported for custodial solution transfers and settlements. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -100,37 +110,42 @@ Each asset entry contains: - asset: Asset symbol - precision: Decimal precision - network: Supported blockchain networks`, - { - rail: railSchema - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/supportedAssetList", { - rail: params.rail.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved supported assets. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get supported assets: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/walletTransfer - Transfer from Exchange Wallet - // ===================================================================== - server.tool( - "binance_us_cust_wallet_transfer", - `Transfer assets from Binance.US exchange wallet to custodial sub-account. + inputSchema: { + rail: railSchema, + }, + }, + async (params: { rail: string }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/supportedAssetList", { + rail: params.rail.toUpperCase(), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved supported assets. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get supported assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/walletTransfer - Transfer from Exchange Wallet + // ===================================================================== + server.registerTool( + "binance_us_cust_wallet_transfer", + { + description: `Transfer assets from Binance.US exchange wallet to custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -144,43 +159,51 @@ Response includes: - transferId: Unique transfer identifier - status: Transfer status (SUCCESS, PENDING, etc.) - createTime: Transfer creation timestamp`, - { - rail: railSchema, - asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), - amount: z.number().positive().describe("Amount to transfer"), - clientOrderId: z.string().optional().describe("Your unique reference ID (auto-generated if not provided)") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/walletTransfer", { - rail: params.rail.toUpperCase(), - asset: params.asset.toUpperCase(), - amount: params.amount, - ...(params.clientOrderId && { clientOrderId: params.clientOrderId }) - }); - - return { - content: [{ - type: "text", - text: `Wallet transfer completed. Transfer ID: ${response.transferId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute wallet transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/custodianTransfer - Transfer from Custodian - // ===================================================================== - server.tool( - "binance_us_cust_transfer", - `Transfer assets from custodial partner account to Binance.US custodial sub-account. + inputSchema: { + rail: railSchema, + asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), + amount: z.number().positive().describe("Amount to transfer"), + clientOrderId: z + .string() + .optional() + .describe("Your unique reference ID (auto-generated if not provided)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/walletTransfer", { + rail: params.rail.toUpperCase(), + asset: params.asset.toUpperCase(), + amount: params.amount, + ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), + }); + + return { + content: [ + { + type: "text", + text: `Wallet transfer completed. Transfer ID: ${response.transferId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to execute wallet transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/custodianTransfer - Transfer from Custodian + // ===================================================================== + server.registerTool( + "binance_us_cust_transfer", + { + description: `Transfer assets from custodial partner account to Binance.US custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -194,43 +217,53 @@ Response includes: - custodyAccountId/custodyAccountName: Custodian account details - status: Transfer status - createTime: Transfer creation timestamp`, - { - rail: railSchema, - asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), - amount: z.number().positive().describe("Amount to transfer"), - clientOrderId: z.string().optional().describe("Your unique reference ID (auto-generated if not provided)") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/custodianTransfer", { - rail: params.rail.toUpperCase(), - asset: params.asset.toUpperCase(), - amount: params.amount, - ...(params.clientOrderId && { clientOrderId: params.clientOrderId }) - }); - - return { - content: [{ - type: "text", - text: `Custodian transfer initiated. Transfer ID: ${response.transferId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute custodian transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/undoTransfer - Undo Transfer - // ===================================================================== - server.tool( - "binance_us_cust_undo_transfer", - `Undo a previous transfer from your custodial partner. + inputSchema: { + rail: railSchema, + asset: z.string().describe("Asset to transfer (e.g., BTC, ETH)"), + amount: z.number().positive().describe("Amount to transfer"), + clientOrderId: z + .string() + .optional() + .describe("Your unique reference ID (auto-generated if not provided)"), + }, + }, + async (params: { rail: string; asset: string; amount: number; clientOrderId?: string }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/custodianTransfer", { + rail: params.rail.toUpperCase(), + asset: params.asset.toUpperCase(), + amount: params.amount, + ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), + }); + + return { + content: [ + { + type: "text", + text: `Custodian transfer initiated. Transfer ID: ${response.transferId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to execute custodian transfer: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/undoTransfer - Undo Transfer + // ===================================================================== + server.registerTool( + "binance_us_cust_undo_transfer", + { + description: `Undo a previous transfer from your custodial partner. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -240,39 +273,44 @@ Response includes: - transferId: New transfer ID for the undo operation - asset: Asset being returned - amount: Amount being returned`, - { - rail: railSchema, - originTransferId: z.string().describe("Original transfer ID to undo") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/undoTransfer", { - rail: params.rail.toUpperCase(), - originTransferId: params.originTransferId - }); - - return { - content: [{ - type: "text", - text: `Transfer undo completed. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to undo transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/walletTransferHistory - Wallet Transfer History - // ===================================================================== - server.tool( - "binance_us_cust_wallet_transfer_history", - `Get history of transfers from Binance.US exchange wallet to custodial sub-account. + inputSchema: { + rail: railSchema, + originTransferId: z.string().describe("Original transfer ID to undo"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/undoTransfer", { + rail: params.rail.toUpperCase(), + originTransferId: params.originTransferId, + }); + + return { + content: [ + { + type: "text", + text: `Transfer undo completed. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to undo transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/walletTransferHistory - Wallet Transfer History + // ===================================================================== + server.registerTool( + "binance_us_cust_wallet_transfer_history", + { + description: `Get history of transfers from Binance.US exchange wallet to custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -282,51 +320,75 @@ Response includes: Each transfer record contains: transferId, clientOrderId, asset, amount, status, createTime, updateTime`, - { - rail: railSchema, - transferId: z.string().optional().describe("Filter by specific transfer ID"), - clientOrderId: z.string().optional().describe("Filter by client order ID"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), - startTime: z.number().optional().describe("Start timestamp (default: 90 days ago)"), - endTime: z.number().optional().describe("End timestamp (default: now)"), - page: z.number().int().positive().optional().default(1).describe("Page number (default: 1)"), - limit: z.number().int().min(1).max(100).optional().default(20).describe("Records per page (default: 20, max: 100)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/walletTransferHistory", { - rail: params.rail.toUpperCase(), - ...(params.transferId && { transferId: params.transferId }), - ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${response.total} wallet transfers. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get wallet transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/custodianTransferHistory - Custodian Transfer History - // ===================================================================== - server.tool( - "binance_us_cust_transfer_history", - `Get history of transfers from custodial partner to Binance.US custodial sub-account. + inputSchema: { + rail: railSchema, + transferId: z.string().optional().describe("Filter by specific transfer ID"), + clientOrderId: z.string().optional().describe("Filter by client order ID"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), + startTime: z.number().optional().describe("Start timestamp (default: 90 days ago)"), + endTime: z.number().optional().describe("End timestamp (default: now)"), + page: z + .number() + .int() + .positive() + .optional() + .default(1) + .describe("Page number (default: 1)"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .default(20) + .describe("Records per page (default: 20, max: 100)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest( + "GET", + "/sapi/v1/custodian/walletTransferHistory", + { + rail: params.rail.toUpperCase(), + ...(params.transferId && { transferId: params.transferId }), + ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }, + ); + + return { + content: [ + { + type: "text", + text: `Retrieved ${response.total} wallet transfers. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get wallet transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/custodianTransferHistory - Custodian Transfer History + // ===================================================================== + server.registerTool( + "binance_us_cust_transfer_history", + { + description: `Get history of transfers from custodial partner to Binance.US custodial sub-account. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -338,90 +400,125 @@ Response includes: Each record contains: transferId, clientOrderId, asset, amount, status, expressTrade flag, createTime, updateTime`, - { - rail: railSchema, - transferId: z.string().optional().describe("Filter by specific transfer ID"), - clientOrderId: z.string().optional().describe("Filter by client order ID"), - expressTradeTransfer: z.boolean().optional().default(false).describe("Filter ExpressTrade transfers only"), - asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), - startTime: z.number().optional().describe("Start timestamp (default: 90 days ago)"), - endTime: z.number().optional().describe("End timestamp (default: now)"), - page: z.number().int().positive().optional().default(1).describe("Page number (default: 1)"), - limit: z.number().int().min(1).max(100).optional().default(20).describe("Records per page (default: 20, max: 100)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/custodianTransferHistory", { - rail: params.rail.toUpperCase(), - ...(params.transferId && { transferId: params.transferId }), - ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), - ...(params.expressTradeTransfer !== undefined && { expressTradeTransfer: params.expressTradeTransfer }), - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${response.total} custodian transfers. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get custodian transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/availableBalance - Get Available Balance - // ===================================================================== - server.tool( - "binance_us_cust_available_balance", - `Get available balance in the custodial sub-account for trading. + inputSchema: { + rail: railSchema, + transferId: z.string().optional().describe("Filter by specific transfer ID"), + clientOrderId: z.string().optional().describe("Filter by client order ID"), + expressTradeTransfer: z + .boolean() + .optional() + .default(false) + .describe("Filter ExpressTrade transfers only"), + asset: z.string().optional().describe("Filter by asset (e.g., BTC)"), + startTime: z.number().optional().describe("Start timestamp (default: 90 days ago)"), + endTime: z.number().optional().describe("End timestamp (default: now)"), + page: z + .number() + .int() + .positive() + .optional() + .default(1) + .describe("Page number (default: 1)"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .default(20) + .describe("Records per page (default: 20, max: 100)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest( + "GET", + "/sapi/v1/custodian/custodianTransferHistory", + { + rail: params.rail.toUpperCase(), + ...(params.transferId && { transferId: params.transferId }), + ...(params.clientOrderId && { clientOrderId: params.clientOrderId }), + ...(params.expressTradeTransfer !== undefined && { + expressTradeTransfer: params.expressTradeTransfer, + }), + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }, + ); + + return { + content: [ + { + type: "text", + text: `Retrieved ${response.total} custodian transfers. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get custodian transfer history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/availableBalance - Get Available Balance + // ===================================================================== + server.registerTool( + "binance_us_cust_available_balance", + { + description: `Get available balance in the custodial sub-account for trading. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Returns the balance available for placing new orders.`, - { - rail: railSchema, - asset: z.string().optional().describe("Filter by specific asset") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/availableBalance", { - rail: params.rail.toUpperCase(), - ...(params.asset && { asset: params.asset.toUpperCase() }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved available balance. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get available balance: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/order - Place Custodial Order - // ===================================================================== - server.tool( - "binance_us_cust_new_order", - `Place a new trade order through the custodial solution. + inputSchema: { + rail: railSchema, + asset: z.string().optional().describe("Filter by specific asset"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/availableBalance", { + rail: params.rail.toUpperCase(), + ...(params.asset && { asset: params.asset.toUpperCase() }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved available balance. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get available balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/order - Place Custodial Order + // ===================================================================== + server.registerTool( + "binance_us_cust_new_order", + { + description: `Place a new trade order through the custodial solution. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -440,59 +537,76 @@ the full amount will be automatically transferred from the custodial partner. Response includes: symbol, orderId, status, type, side, price, quantity, executedQty, and expressTradeFlag`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair (e.g., BTCUSD, ETHUSD)"), - side: orderSideEnum.describe("Order side: BUY or SELL"), - type: orderTypeEnum.describe("Order type"), - timeInForce: timeInForceEnum.optional().describe("GTC (Good Til Canceled), IOC (Immediate or Cancel), FOK (Fill or Kill)"), - quantity: z.number().positive().optional().describe("Order quantity in base asset"), - quoteOrderQty: z.number().positive().optional().describe("Order quantity in quote asset (MARKET orders only)"), - price: z.number().positive().optional().describe("Order price (required for LIMIT orders)"), - stopPrice: z.number().positive().optional().describe("Stop/trigger price for stop orders"), - icebergQty: z.number().positive().optional().describe("Iceberg order quantity"), - asset: z.string().optional().describe("Asset for ExpressTrade (the asset being sold)"), - allowExpressTrade: z.boolean().optional().default(false).describe("Enable ExpressTrade for auto-funding") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/order", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase(), - side: params.side, - type: params.type, - ...(params.timeInForce && { timeInForce: params.timeInForce }), - ...(params.quantity && { quantity: params.quantity }), - ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), - ...(params.price && { price: params.price }), - ...(params.stopPrice && { stopPrice: params.stopPrice }), - ...(params.icebergQty && { icebergQty: params.icebergQty }), - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.allowExpressTrade !== undefined && { allowExpressTrade: params.allowExpressTrade }) - }); - - return { - content: [{ - type: "text", - text: `Custodial order placed. Order ID: ${response.orderId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place custodial order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/custodian/ocoOrder - Place Custodial OCO Order - // ===================================================================== - server.tool( - "binance_us_cust_oco_order", - `Place a new OCO (One-Cancels-the-Other) order through the custodial solution. + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair (e.g., BTCUSD, ETHUSD)"), + side: orderSideEnum.describe("Order side: BUY or SELL"), + type: orderTypeEnum.describe("Order type"), + timeInForce: timeInForceEnum + .optional() + .describe("GTC (Good Til Canceled), IOC (Immediate or Cancel), FOK (Fill or Kill)"), + quantity: z.number().positive().optional().describe("Order quantity in base asset"), + quoteOrderQty: z + .number() + .positive() + .optional() + .describe("Order quantity in quote asset (MARKET orders only)"), + price: z.number().positive().optional().describe("Order price (required for LIMIT orders)"), + stopPrice: z.number().positive().optional().describe("Stop/trigger price for stop orders"), + icebergQty: z.number().positive().optional().describe("Iceberg order quantity"), + asset: z.string().optional().describe("Asset for ExpressTrade (the asset being sold)"), + allowExpressTrade: z + .boolean() + .optional() + .default(false) + .describe("Enable ExpressTrade for auto-funding"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/order", { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + side: params.side, + type: params.type, + ...(params.timeInForce && { timeInForce: params.timeInForce }), + ...(params.quantity && { quantity: params.quantity }), + ...(params.quoteOrderQty && { quoteOrderQty: params.quoteOrderQty }), + ...(params.price && { price: params.price }), + ...(params.stopPrice && { stopPrice: params.stopPrice }), + ...(params.icebergQty && { icebergQty: params.icebergQty }), + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.allowExpressTrade !== undefined && { + allowExpressTrade: params.allowExpressTrade, + }), + }); + + return { + content: [ + { + type: "text", + text: `Custodial order placed. Order ID: ${response.orderId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to place custodial order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/custodian/ocoOrder - Place Custodial OCO Order + // ===================================================================== + server.registerTool( + "binance_us_cust_oco_order", + { + description: `Place a new OCO (One-Cancels-the-Other) order through the custodial solution. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -508,63 +622,72 @@ Quantity: Both legs must have the same quantity (iceberg qty can differ). Note: OCO counts as 2 orders against rate limits. Response includes orderListId, orders array, and orderReports with details.`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair (e.g., BTCUSD, ETHUSD)"), - side: orderSideEnum.describe("Order side: BUY or SELL"), - quantity: z.number().positive().describe("Order quantity (same for both legs)"), - price: z.number().positive().describe("Limit order price"), - stopPrice: z.number().positive().describe("Stop trigger price"), - limitClientOrderId: z.string().optional().describe("Unique ID for the limit order"), - limitIcebergQty: z.number().positive().optional().describe("Iceberg qty for limit leg"), - stopClientOrderId: z.string().optional().describe("Unique ID for the stop leg"), - stopLimitPrice: z.number().positive().optional().describe("Limit price for stop-limit leg"), - stopIcebergQty: z.number().positive().optional().describe("Iceberg qty for stop leg"), - stopLimitTimeInForce: timeInForceEnum.optional().describe("Time in force for stop-limit leg"), - asset: z.string().optional().describe("Asset for ExpressTrade"), - allowExpressTrade: z.boolean().optional().default(false).describe("Enable ExpressTrade") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/custodian/ocoOrder", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase(), - side: params.side, - quantity: params.quantity, - price: params.price, - stopPrice: params.stopPrice, - ...(params.limitClientOrderId && { limitClientOrderId: params.limitClientOrderId }), - ...(params.limitIcebergQty && { limitIcebergQty: params.limitIcebergQty }), - ...(params.stopClientOrderId && { stopClientOrderId: params.stopClientOrderId }), - ...(params.stopLimitPrice && { stopLimitPrice: params.stopLimitPrice }), - ...(params.stopIcebergQty && { stopIcebergQty: params.stopIcebergQty }), - ...(params.stopLimitTimeInForce && { stopLimitTimeInForce: params.stopLimitTimeInForce }), - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.allowExpressTrade !== undefined && { allowExpressTrade: params.allowExpressTrade }) - }); - - return { - content: [{ - type: "text", - text: `Custodial OCO order placed. Order List ID: ${response.orderListId}, Status: ${response.listOrderStatus}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place custodial OCO order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/openOrders - Get Open Orders - // ===================================================================== - server.tool( - "binance_us_cust_open_orders", - `Get all open custodial trade orders. + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair (e.g., BTCUSD, ETHUSD)"), + side: orderSideEnum.describe("Order side: BUY or SELL"), + quantity: z.number().positive().describe("Order quantity (same for both legs)"), + price: z.number().positive().describe("Limit order price"), + stopPrice: z.number().positive().describe("Stop trigger price"), + limitClientOrderId: z.string().optional().describe("Unique ID for the limit order"), + limitIcebergQty: z.number().positive().optional().describe("Iceberg qty for limit leg"), + stopClientOrderId: z.string().optional().describe("Unique ID for the stop leg"), + stopLimitPrice: z.number().positive().optional().describe("Limit price for stop-limit leg"), + stopIcebergQty: z.number().positive().optional().describe("Iceberg qty for stop leg"), + stopLimitTimeInForce: timeInForceEnum + .optional() + .describe("Time in force for stop-limit leg"), + asset: z.string().optional().describe("Asset for ExpressTrade"), + allowExpressTrade: z.boolean().optional().default(false).describe("Enable ExpressTrade"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/custodian/ocoOrder", { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + side: params.side, + quantity: params.quantity, + price: params.price, + stopPrice: params.stopPrice, + ...(params.limitClientOrderId && { limitClientOrderId: params.limitClientOrderId }), + ...(params.limitIcebergQty && { limitIcebergQty: params.limitIcebergQty }), + ...(params.stopClientOrderId && { stopClientOrderId: params.stopClientOrderId }), + ...(params.stopLimitPrice && { stopLimitPrice: params.stopLimitPrice }), + ...(params.stopIcebergQty && { stopIcebergQty: params.stopIcebergQty }), + ...(params.stopLimitTimeInForce && { stopLimitTimeInForce: params.stopLimitTimeInForce }), + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.allowExpressTrade !== undefined && { + allowExpressTrade: params.allowExpressTrade, + }), + }); + + return { + content: [ + { + type: "text", + text: `Custodial OCO order placed. Order List ID: ${response.orderListId}, Status: ${response.listOrderStatus}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to place custodial OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/openOrders - Get Open Orders + // ===================================================================== + server.registerTool( + "binance_us_cust_open_orders", + { + description: `Get all open custodial trade orders. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -573,80 +696,93 @@ Response includes orderListId, orders array, and orderReports with details.`, Response is an array of open orders with: symbol, orderId, price, origQty, executedQty, status, type, side, stopPrice, time, updateTime, isWorking, expressTradeFlag`, - { - rail: railSchema, - symbol: z.string().optional().describe("Trading pair (e.g., BTCUSD). Recommended to always specify.") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/openOrders", { - rail: params.rail.toUpperCase(), - ...(params.symbol && { symbol: params.symbol.toUpperCase() }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${Array.isArray(response) ? response.length : 0} open orders. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get open orders: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/order - Get Order - // ===================================================================== - server.tool( - "binance_us_cust_get_order", - `Get details of a specific custodial trade order. + inputSchema: { + rail: railSchema, + symbol: z + .string() + .optional() + .describe("Trading pair (e.g., BTCUSD). Recommended to always specify."), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/openOrders", { + rail: params.rail.toUpperCase(), + ...(params.symbol && { symbol: params.symbol.toUpperCase() }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${Array.isArray(response) ? response.length : 0} open orders. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get open orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/order - Get Order + // ===================================================================== + server.registerTool( + "binance_us_cust_get_order", + { + description: `Get details of a specific custodial trade order. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Response includes: symbol, orderId, price, origQty, executedQty, cummulativeQuoteQty, status, timeInForce, type, side, stopPrice, icebergQty, time, updateTime, isWorking, expressTradeFlag`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), - orderId: z.number().int().describe("Order ID to query") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/order", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase(), - orderId: params.orderId - }); - - return { - content: [{ - type: "text", - text: `Order retrieved. Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/orderHistory - Get Order History - // ===================================================================== - server.tool( - "binance_us_cust_order_history", - `Get historical custodial trade orders. + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), + orderId: z.number().int().describe("Order ID to query"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/order", { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + orderId: params.orderId, + }); + + return { + content: [ + { + type: "text", + text: `Order retrieved. Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/orderHistory - Get Order History + // ===================================================================== + server.registerTool( + "binance_us_cust_order_history", + { + description: `Get historical custodial trade orders. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -654,47 +790,62 @@ If symbol is not sent, orders for all symbols will be returned. Response is an array of orders with full details including status, executedQty, and expressTradeFlag.`, - { - rail: railSchema, - symbol: z.string().optional().describe("Trading pair (e.g., BTCUSD). If omitted, returns all symbols."), - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - fromId: z.number().int().optional().describe("Start from this order ID"), - limit: z.number().int().min(1).max(1000).optional().default(200).describe("Max records (default: 200)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/orderHistory", { - rail: params.rail.toUpperCase(), - ...(params.symbol && { symbol: params.symbol.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${Array.isArray(response) ? response.length : 0} historical orders. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get order history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/tradeHistory - Get Trade History - // ===================================================================== - server.tool( - "binance_us_cust_trade_history", - `Get historical custodial trades (filled orders). + inputSchema: { + rail: railSchema, + symbol: z + .string() + .optional() + .describe("Trading pair (e.g., BTCUSD). If omitted, returns all symbols."), + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + fromId: z.number().int().optional().describe("Start from this order ID"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .default(200) + .describe("Max records (default: 200)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/orderHistory", { + rail: params.rail.toUpperCase(), + ...(params.symbol && { symbol: params.symbol.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${Array.isArray(response) ? response.length : 0} historical orders. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get order history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/tradeHistory - Get Trade History + // ===================================================================== + server.registerTool( + "binance_us_cust_trade_history", + { + description: `Get historical custodial trades (filled orders). ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -702,137 +853,166 @@ Returns actual executed trades with price, quantity, and commission details. Response includes for each trade: symbol, price, qty, quoteQty, time, isBuyer, isMaker, isBestMatch, orderId, commission, commissionAsset`, - { - rail: railSchema, - symbol: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), - orderId: z.number().int().optional().describe("Filter by order ID"), - startTime: z.number().optional().describe("Start timestamp"), - endTime: z.number().optional().describe("End timestamp"), - fromId: z.number().int().optional().describe("Start from this trade ID"), - limit: z.number().int().min(1).max(1000).optional().default(200).describe("Max records (default: 200)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/tradeHistory", { - rail: params.rail.toUpperCase(), - ...(params.symbol && { symbol: params.symbol.toUpperCase() }), - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.fromId && { fromId: params.fromId }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${Array.isArray(response) ? response.length : 0} trades. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get trade history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // DELETE /sapi/v1/custodian/cancelOrder - Cancel Order - // ===================================================================== - server.tool( - "binance_us_cust_cancel_order", - `Cancel an active custodial trade order. + inputSchema: { + rail: railSchema, + symbol: z.string().optional().describe("Trading pair (e.g., BTCUSD)"), + orderId: z.number().int().optional().describe("Filter by order ID"), + startTime: z.number().optional().describe("Start timestamp"), + endTime: z.number().optional().describe("End timestamp"), + fromId: z.number().int().optional().describe("Start from this trade ID"), + limit: z + .number() + .int() + .min(1) + .max(1000) + .optional() + .default(200) + .describe("Max records (default: 200)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/tradeHistory", { + rail: params.rail.toUpperCase(), + ...(params.symbol && { symbol: params.symbol.toUpperCase() }), + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.fromId && { fromId: params.fromId }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${Array.isArray(response) ? response.length : 0} trades. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get trade history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // DELETE /sapi/v1/custodian/cancelOrder - Cancel Order + // ===================================================================== + server.registerTool( + "binance_us_cust_cancel_order", + { + description: `Cancel an active custodial trade order. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY Either orderId or origClientOrderId must be provided. Response includes the canceled order details with status: CANCELED`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), - orderId: z.number().int().optional().describe("Order ID to cancel"), - origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), - newClientOrderId: z.string().optional().describe("New client order ID for this cancel operation") - }, - async (params) => { - try { - if (!params.orderId && !params.origClientOrderId) { - throw new Error("Either orderId or origClientOrderId must be provided"); - } - - const response = await makeSignedRequest("DELETE", "/sapi/v1/custodian/cancelOrder", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase(), - ...(params.orderId && { orderId: params.orderId }), - ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }) - }); - - return { - content: [{ - type: "text", - text: `Order canceled. Order ID: ${response.orderId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel order: ${errorMessage}` }], - isError: true - }; - } + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), + orderId: z.number().int().optional().describe("Order ID to cancel"), + origClientOrderId: z.string().optional().describe("Original client order ID to cancel"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for this cancel operation"), + }, + }, + async (params) => { + try { + if (!params.orderId && !params.origClientOrderId) { + throw new Error("Either orderId or origClientOrderId must be provided"); } - ); - // ===================================================================== - // DELETE /sapi/v1/custodian/cancelOrdersBySymbol - Cancel All Orders for Symbol - // ===================================================================== - server.tool( - "binance_us_cust_cancel_orders_symbol", - `Cancel all active custodial orders for a specific trading pair. + const response = await makeSignedRequest("DELETE", "/sapi/v1/custodian/cancelOrder", { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + ...(params.orderId && { orderId: params.orderId }), + ...(params.origClientOrderId && { origClientOrderId: params.origClientOrderId }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + }); + + return { + content: [ + { + type: "text", + text: `Order canceled. Order ID: ${response.orderId}, Status: ${response.status}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // DELETE /sapi/v1/custodian/cancelOrdersBySymbol - Cancel All Orders for Symbol + // ===================================================================== + server.registerTool( + "binance_us_cust_cancel_orders_symbol", + { + description: `Cancel all active custodial orders for a specific trading pair. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY This includes OCO orders. Use with caution. Response is an array of all canceled orders.`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair to cancel all orders for (e.g., BTCUSD)") - }, - async (params) => { - try { - const response = await makeSignedRequest("DELETE", "/sapi/v1/custodian/cancelOrdersBySymbol", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `All orders canceled for ${params.symbol}. Canceled ${Array.isArray(response) ? response.length : 0} orders. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel orders: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // DELETE /sapi/v1/custodian/cancelOcoOrder - Cancel OCO Order - // ===================================================================== - server.tool( - "binance_us_cust_cancel_oco", - `Cancel an entire OCO (One-Cancels-the-Other) order list. + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair to cancel all orders for (e.g., BTCUSD)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest( + "DELETE", + "/sapi/v1/custodian/cancelOrdersBySymbol", + { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + }, + ); + + return { + content: [ + { + type: "text", + text: `All orders canceled for ${params.symbol}. Canceled ${Array.isArray(response) ? response.length : 0} orders. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // DELETE /sapi/v1/custodian/cancelOcoOrder - Cancel OCO Order + // ===================================================================== + server.registerTool( + "binance_us_cust_cancel_oco", + { + description: `Cancel an entire OCO (One-Cancels-the-Other) order list. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -840,45 +1020,53 @@ This cancels both legs of the OCO order. Response includes orderListId, orders array, and orderReports with canceled order details.`, - { - rail: railSchema, - symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), - orderListId: z.number().int().describe("OCO order list ID to cancel"), - listClientOrderId: z.string().optional().describe("List client order ID"), - newClientOrderId: z.string().optional().describe("New client order ID for cancel operation") - }, - async (params) => { - try { - const response = await makeSignedRequest("DELETE", "/sapi/v1/custodian/cancelOcoOrder", { - rail: params.rail.toUpperCase(), - symbol: params.symbol.toUpperCase(), - orderListId: params.orderListId, - ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), - ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }) - }); - - return { - content: [{ - type: "text", - text: `OCO order canceled. List ID: ${response.orderListId}, Status: ${response.listOrderStatus}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to cancel OCO order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/settlementSetting - Get Settlement Settings - // ===================================================================== - server.tool( - "binance_us_cust_settlement_settings", - `Get current settlement settings for custodial solution. + inputSchema: { + rail: railSchema, + symbol: z.string().describe("Trading pair (e.g., BTCUSD)"), + orderListId: z.number().int().describe("OCO order list ID to cancel"), + listClientOrderId: z.string().optional().describe("List client order ID"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for cancel operation"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("DELETE", "/sapi/v1/custodian/cancelOcoOrder", { + rail: params.rail.toUpperCase(), + symbol: params.symbol.toUpperCase(), + orderListId: params.orderListId, + ...(params.listClientOrderId && { listClientOrderId: params.listClientOrderId }), + ...(params.newClientOrderId && { newClientOrderId: params.newClientOrderId }), + }); + + return { + content: [ + { + type: "text", + text: `OCO order canceled. List ID: ${response.orderListId}, Status: ${response.listOrderStatus}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to cancel OCO order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/settlementSetting - Get Settlement Settings + // ===================================================================== + server.registerTool( + "binance_us_cust_settlement_settings", + { + description: `Get current settlement settings for custodial solution. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -888,37 +1076,42 @@ Response includes: - settlementActive: Whether auto-settlement is enabled - frequencyInHours: Settlement frequency (e.g., 24 hours) - nextTriggerTime: Timestamp of next scheduled settlement`, - { - rail: railSchema - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/settlementSetting", { - rail: params.rail.toUpperCase() - }); - - return { - content: [{ - type: "text", - text: `Settlement settings retrieved. Active: ${response.settlementActive}, Next: ${new Date(response.nextTriggerTime).toISOString()}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get settlement settings: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/custodian/settlementHistory - Get Settlement History - // ===================================================================== - server.tool( - "binance_us_cust_settlement_history", - `Get historical settlement records for custodial solution. + inputSchema: { + rail: railSchema, + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/settlementSetting", { + rail: params.rail.toUpperCase(), + }); + + return { + content: [ + { + type: "text", + text: `Settlement settings retrieved. Active: ${response.settlementActive}, Next: ${new Date(response.nextTriggerTime).toISOString()}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get settlement settings: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/custodian/settlementHistory - Get Settlement History + // ===================================================================== + server.registerTool( + "binance_us_cust_settlement_history", + { + description: `Get historical settlement records for custodial solution. ⚠️ REQUIRES CUSTODIAL SOLUTION API KEY @@ -933,36 +1126,53 @@ Each record contains: - triggerTime: When settlement was triggered - settlementId: Unique settlement identifier - settlementAssets: Array of assets settled with amounts and addresses`, - { - rail: railSchema, - startTime: z.number().optional().describe("Start timestamp"), - endTime: z.number().optional().describe("End timestamp"), - limit: z.number().int().min(1).max(100).optional().default(5).describe("Max records (default: 5, max: 100)"), - page: z.number().int().positive().optional().default(1).describe("Page number (default: 1)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/custodian/settlementHistory", { - rail: params.rail.toUpperCase(), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.limit && { limit: params.limit }), - ...(params.page && { page: params.page }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${response.total} settlement records. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get settlement history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + rail: railSchema, + startTime: z.number().optional().describe("Start timestamp"), + endTime: z.number().optional().describe("End timestamp"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .default(5) + .describe("Max records (default: 5, max: 100)"), + page: z + .number() + .int() + .positive() + .optional() + .default(1) + .describe("Page number (default: 1)"), + }, + }, + async (params) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/custodian/settlementHistory", { + rail: params.rail.toUpperCase(), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.limit && { limit: params.limit }), + ...(params.page && { page: params.page }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${response.total} settlement records. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get settlement history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/general/index.ts b/src/tools/general/index.ts index 36fa8575..89d3776a 100644 --- a/src/tools/general/index.ts +++ b/src/tools/general/index.ts @@ -1,148 +1,169 @@ // src/tools/general/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { binanceUsRequest } from "../../config/binanceUsClient.js"; export function registerGeneralTools(server: McpServer) { - // binance_us_ping - Test connectivity to Binance.US - server.tool( - "binance_us_ping", - "Test connectivity to the Binance.US API. Returns empty object if successful.", - {}, - async () => { - try { - const result = await binanceUsRequest("GET", "/api/v3/ping", {}, false); - return { - content: [ - { - type: "text", - text: `Binance.US API connection successful. Response: ${JSON.stringify(result)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to ping Binance.US API: ${errorMessage}` } - ], - isError: true - }; - } - } - ); - - // binance_us_server_time - Get server time - server.tool( - "binance_us_server_time", - "Get the current server time from Binance.US exchange.", - {}, - async () => { - try { - const result = await binanceUsRequest("GET", "/api/v3/time", {}, false); - const serverTime = new Date(result.serverTime).toISOString(); - return { - content: [ - { - type: "text", - text: `Binance.US server time: ${serverTime} (${result.serverTime}). Response: ${JSON.stringify(result)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get server time: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + // binance_us_ping - Test connectivity to Binance.US + server.registerTool( + "binance_us_ping", + { description: "Test connectivity to the Binance.US API. Returns empty object if successful." }, + async () => { + try { + const result = await binanceUsRequest("GET", "/api/v3/ping", {}, false); + + return { + content: [ + { + type: "text", + text: `Binance.US API connection successful. Response: ${JSON.stringify(result)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to ping Binance.US API: ${errorMessage}` }], + isError: true, + }; + } + }, + ); - // binance_us_system_status - Get system maintenance status (SIGNED) - server.tool( - "binance_us_system_status", + // binance_us_server_time - Get server time + server.registerTool( + "binance_us_server_time", + { description: "Get the current server time from Binance.US exchange." }, + async () => { + try { + const result = await binanceUsRequest("GET", "/api/v3/time", {}, false); + const serverTime = new Date(result.serverTime).toISOString(); + + return { + content: [ + { + type: "text", + text: `Binance.US server time: ${serverTime} (${result.serverTime}). Response: ${JSON.stringify(result)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get server time: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // binance_us_system_status - Get system maintenance status (SIGNED) + server.registerTool( + "binance_us_system_status", + { + description: "Check if Binance.US system is under maintenance. Status 0 = normal, 1 = system maintenance. Requires API key authentication.", - {}, - async () => { - try { - const result = await binanceUsRequest("GET", "/sapi/v1/system/status", {}, true); - const statusText = result.status === 0 ? "Normal" : "System Maintenance"; - return { - content: [ - { - type: "text", - text: `Binance.US system status: ${statusText} (${result.status}). Response: ${JSON.stringify(result)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get system status: ${errorMessage}` } - ], - isError: true - }; - } - } - ); + }, + async () => { + try { + const result = await binanceUsRequest("GET", "/sapi/v1/system/status", {}, true); + const statusText = result.status === 0 ? "Normal" : "System Maintenance"; + + return { + content: [ + { + type: "text", + text: `Binance.US system status: ${statusText} (${result.status}). Response: ${JSON.stringify(result)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - // binance_us_exchange_info - Get exchange information - server.tool( - "binance_us_exchange_info", + return { + content: [{ type: "text", text: `Failed to get system status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // binance_us_exchange_info - Get exchange information + server.registerTool( + "binance_us_exchange_info", + { + description: "Get current exchange trading rules and trading pair information from Binance.US. Can filter by specific symbol(s) or permissions.", - { - symbol: z.string().optional().describe("Single trading pair symbol to filter (e.g., BTCUSD). Cannot be used with 'symbols' parameter."), - symbols: z.array(z.string()).optional().describe("Array of trading pair symbols to filter (e.g., ['BTCUSD', 'ETHUSD']). Cannot be used with 'symbol' parameter."), - permissions: z.array(z.string()).optional().describe("Filter by trading permissions. Default is ['SPOT'].") - }, - async ({ symbol, symbols, permissions }) => { - try { - const params: Record = {}; - - // symbol and symbols are mutually exclusive - if (symbol && symbols) { - return { - content: [ - { type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols' parameters. Use one or the other." } - ], - isError: true - }; - } - - if (symbol) { - params.symbol = symbol; - } else if (symbols && symbols.length > 0) { - params.symbols = JSON.stringify(symbols); - } - - if (permissions && permissions.length > 0) { - params.permissions = permissions.join(","); - } - - const result = await binanceUsRequest("GET", "/api/v3/exchangeInfo", params, false); - - const symbolCount = result.symbols?.length || 0; - return { - content: [ - { - type: "text", - text: `Retrieved exchange info. Total symbols: ${symbolCount}. Server time: ${result.serverTime}. Timezone: ${result.timezone}. Response: ${JSON.stringify(result, null, 2)}` - } - ] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [ - { type: "text", text: `Failed to get exchange info: ${errorMessage}` } - ], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Single trading pair symbol to filter (e.g., BTCUSD). Cannot be used with 'symbols' parameter.", + ), + symbols: z + .array(z.string()) + .optional() + .describe( + "Array of trading pair symbols to filter (e.g., ['BTCUSD', 'ETHUSD']). Cannot be used with 'symbol' parameter.", + ), + permissions: z + .array(z.string()) + .optional() + .describe("Filter by trading permissions. Default is ['SPOT']."), + }, + }, + async ({ symbol, symbols, permissions }) => { + try { + const params: Record = {}; + + // symbol and symbols are mutually exclusive + if (symbol && symbols) { + return { + content: [ + { + type: "text", + text: "Error: Cannot specify both 'symbol' and 'symbols' parameters. Use one or the other.", + }, + ], + isError: true, + }; + } + + if (symbol) { + params.symbol = symbol; + } else if (symbols && symbols.length > 0) { + params.symbols = JSON.stringify(symbols); + } + + if (permissions && permissions.length > 0) { + params.permissions = permissions.join(","); } - ); + + const result = await binanceUsRequest("GET", "/api/v3/exchangeInfo", params, false); + + const symbolCount = result.symbols?.length || 0; + + return { + content: [ + { + type: "text", + text: `Retrieved exchange info. Total symbols: ${symbolCount}. Server time: ${result.serverTime}. Timezone: ${result.timezone}. Response: ${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get exchange info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/market/index.ts b/src/tools/market/index.ts index f5d397aa..3700b1b9 100644 --- a/src/tools/market/index.ts +++ b/src/tools/market/index.ts @@ -1,521 +1,682 @@ // src/tools/market/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; -import { - binanceUsRequest, - formatKline, - formatAggTrade, - ORDER_BOOK_VALID_LIMITS, - KLINE_INTERVALS, - ROLLING_WINDOW_SIZES, - MAX_TRADES_LIMIT, - MAX_KLINES_LIMIT, - BinanceUsApiError, - RateLimitError, - IpBanError, - type KlineRaw, - type AggTradeResponse + +import { + type AggTradeResponse, + BinanceUsApiError, + binanceUsRequest, + formatAggTrade, + formatKline, + IpBanError, + KLINE_INTERVALS, + type KlineRaw, + MAX_KLINES_LIMIT, + MAX_TRADES_LIMIT, + ORDER_BOOK_VALID_LIMITS, + RateLimitError, + ROLLING_WINDOW_SIZES, } from "../../config/binanceUsClient.js"; /** * Format error response with helpful details */ function formatError(error: unknown): { content: { type: "text"; text: string }[]; isError: true } { - if (error instanceof RateLimitError) { - return { - content: [{ - type: "text", - text: `Rate limit exceeded. Please retry after ${error.retryAfter} seconds. Consider using WebSocket streams for real-time data.` - }], - isError: true - }; - } - if (error instanceof IpBanError) { - return { - content: [{ - type: "text", - text: `IP temporarily banned. Ban will be lifted after ${error.retryAfter} seconds. Please reduce request frequency.` - }], - isError: true - }; - } - if (error instanceof BinanceUsApiError) { - return { - content: [{ - type: "text", - text: `Binance.US API Error [${error.code}]: ${error.message}` - }], - isError: true - }; - } - const errorMessage = error instanceof Error ? error.message : String(error); + if (error instanceof RateLimitError) { + return { + content: [ + { + type: "text", + text: `Rate limit exceeded. Please retry after ${error.retryAfter} seconds. Consider using WebSocket streams for real-time data.`, + }, + ], + isError: true, + }; + } + if (error instanceof IpBanError) { + return { + content: [ + { + type: "text", + text: `IP temporarily banned. Ban will be lifted after ${error.retryAfter} seconds. Please reduce request frequency.`, + }, + ], + isError: true, + }; + } + if (error instanceof BinanceUsApiError) { return { - content: [{ type: "text", text: errorMessage }], - isError: true + content: [ + { + type: "text", + text: `Binance.US API Error [${error.code}]: ${error.message}`, + }, + ], + isError: true, }; + } + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: errorMessage }], + isError: true, + }; } /** * Register Market Data tools for Binance.US - * + * * These are public endpoints that don't require authentication. * Includes: order book, recent trades, klines, ticker data, etc. */ export function registerMarketTools(server: McpServer) { - // binance_us_order_book - Get order book depth - server.tool( - "binance_us_order_book", + // binance_us_order_book - Get order book depth + server.registerTool( + "binance_us_order_book", + { + description: "Get order book depth (bids and asks) for a trading pair on Binance.US. Returns price levels with quantities. Weight varies based on limit (1-100: weight 1, 101-500: weight 5, 501-1000: weight 10, 1001-5000: weight 50).", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), - limit: z.number() - .int() - .min(1) - .max(5000) - .optional() - .describe(`Number of price levels. Valid values: ${ORDER_BOOK_VALID_LIMITS.join(", ")}. Default 100, max 5000.`) - }, - async ({ symbol, limit }) => { - try { - const params: Record = { symbol }; - if (limit !== undefined) params.limit = limit; - - const result = await binanceUsRequest("GET", "/api/v3/depth", params, false); - - const bestBid = result.bids?.[0] || ["N/A", "N/A"]; - const bestAsk = result.asks?.[0] || ["N/A", "N/A"]; - - return { - content: [{ - type: "text", - text: `Order Book for ${symbol}\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Last Update ID: ${result.lastUpdateId}\n` + - `Bids: ${result.bids?.length || 0} levels | Asks: ${result.asks?.length || 0} levels\n` + - `Best Bid: ${bestBid[0]} @ ${bestBid[1]} qty\n` + - `Best Ask: ${bestAsk[0]} @ ${bestAsk[1]} qty\n` + - `Spread: ${bestBid[0] !== "N/A" && bestAsk[0] !== "N/A" ? - (parseFloat(bestAsk[0]) - parseFloat(bestBid[0])).toFixed(8) : "N/A"}\n\n` + - `Full Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } - } - ); + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + limit: z + .number() + .int() + .min(1) + .max(5000) + .optional() + .describe( + `Number of price levels. Valid values: ${ORDER_BOOK_VALID_LIMITS.join(", ")}. Default 100, max 5000.`, + ), + }, + }, + async ({ symbol, limit }) => { + try { + const params: Record = { symbol }; + if (limit !== undefined) params.limit = limit; + + const result = await binanceUsRequest("GET", "/api/v3/depth", params, false); - // binance_us_recent_trades - Get recent trades - server.tool( - "binance_us_recent_trades", + const bestBid = result.bids?.[0] || ["N/A", "N/A"]; + const bestAsk = result.asks?.[0] || ["N/A", "N/A"]; + + return { + content: [ + { + type: "text", + text: + `Order Book for ${symbol}\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Last Update ID: ${result.lastUpdateId}\n` + + `Bids: ${result.bids?.length || 0} levels | Asks: ${result.asks?.length || 0} levels\n` + + `Best Bid: ${bestBid[0]} @ ${bestBid[1]} qty\n` + + `Best Ask: ${bestAsk[0]} @ ${bestAsk[1]} qty\n` + + `Spread: ${ + bestBid[0] !== "N/A" && bestAsk[0] !== "N/A" + ? (parseFloat(bestAsk[0]) - parseFloat(bestBid[0])).toFixed(8) + : "N/A" + }\n\n` + + `Full Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_recent_trades - Get recent trades + server.registerTool( + "binance_us_recent_trades", + { + description: "Get recent trades for a trading pair on Binance.US. Returns trade ID, price, quantity, time, and maker/taker info.", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), - limit: z.number().int().min(1).max(MAX_TRADES_LIMIT).optional() - .describe(`Number of trades to return. Default 500, max ${MAX_TRADES_LIMIT}.`) - }, - async ({ symbol, limit }) => { - try { - const params: Record = { symbol }; - if (limit !== undefined) params.limit = limit; - - const result = await binanceUsRequest("GET", "/api/v3/trades", params, false); - - const latestTrade = result[result.length - 1]; - const oldestTrade = result[0]; - - return { - content: [{ - type: "text", - text: `Recent Trades for ${symbol}\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Total trades: ${result.length}\n` + - `Time range: ${new Date(oldestTrade?.time).toISOString()} to ${new Date(latestTrade?.time).toISOString()}\n` + - `Latest: ${latestTrade?.price} @ ${latestTrade?.qty} qty (ID: ${latestTrade?.id})\n\n` + - `Full Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } - } - ); + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + limit: z + .number() + .int() + .min(1) + .max(MAX_TRADES_LIMIT) + .optional() + .describe(`Number of trades to return. Default 500, max ${MAX_TRADES_LIMIT}.`), + }, + }, + async ({ symbol, limit }) => { + try { + const params: Record = { symbol }; + if (limit !== undefined) params.limit = limit; - // binance_us_historical_trades - Get older trades (MARKET_DATA) - server.tool( - "binance_us_historical_trades", + const result = await binanceUsRequest("GET", "/api/v3/trades", params, false); + + const latestTrade = result[result.length - 1]; + const oldestTrade = result[0]; + + return { + content: [ + { + type: "text", + text: + `Recent Trades for ${symbol}\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Total trades: ${result.length}\n` + + `Time range: ${new Date(oldestTrade?.time).toISOString()} to ${new Date(latestTrade?.time).toISOString()}\n` + + `Latest: ${latestTrade?.price} @ ${latestTrade?.qty} qty (ID: ${latestTrade?.id})\n\n` + + `Full Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_historical_trades - Get older trades (MARKET_DATA) + server.registerTool( + "binance_us_historical_trades", + { + description: "Get older historical trades for a trading pair. Requires API key with MARKET_DATA permission.", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), - limit: z.number().int().min(1).max(MAX_TRADES_LIMIT).optional() - .describe(`Number of trades. Default 500, max ${MAX_TRADES_LIMIT}.`), - fromId: z.number().int().positive().optional() - .describe("Trade ID to fetch from (inclusive).") - }, - async ({ symbol, limit, fromId }) => { - try { - const params: Record = { symbol }; - if (limit !== undefined) params.limit = limit; - if (fromId !== undefined) params.fromId = fromId; - - const result = await binanceUsRequest("GET", "/api/v3/historicalTrades", params, false, true); - - const latestTrade = result[result.length - 1]; - const oldestTrade = result[0]; - - return { - content: [{ - type: "text", - text: `Historical Trades for ${symbol}\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Total trades: ${result.length}\n` + - `Trade ID range: ${oldestTrade?.id} to ${latestTrade?.id}\n` + - `Time range: ${new Date(oldestTrade?.time).toISOString()} to ${new Date(latestTrade?.time).toISOString()}\n\n` + - `Full Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } - } - ); + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + limit: z + .number() + .int() + .min(1) + .max(MAX_TRADES_LIMIT) + .optional() + .describe(`Number of trades. Default 500, max ${MAX_TRADES_LIMIT}.`), + fromId: z + .number() + .int() + .positive() + .optional() + .describe("Trade ID to fetch from (inclusive)."), + }, + }, + async ({ symbol, limit, fromId }) => { + try { + const params: Record = { symbol }; + if (limit !== undefined) params.limit = limit; + if (fromId !== undefined) params.fromId = fromId; + + const result = await binanceUsRequest( + "GET", + "/api/v3/historicalTrades", + params, + false, + true, + ); - // binance_us_agg_trades - Get aggregate trades - server.tool( - "binance_us_agg_trades", + const latestTrade = result[result.length - 1]; + const oldestTrade = result[0]; + + return { + content: [ + { + type: "text", + text: + `Historical Trades for ${symbol}\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Total trades: ${result.length}\n` + + `Trade ID range: ${oldestTrade?.id} to ${latestTrade?.id}\n` + + `Time range: ${new Date(oldestTrade?.time).toISOString()} to ${new Date(latestTrade?.time).toISOString()}\n\n` + + `Full Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_agg_trades - Get aggregate trades + server.registerTool( + "binance_us_agg_trades", + { + description: "Get compressed aggregate trades. Trades with same time, order, and price are aggregated.", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), - fromId: z.number().int().positive().optional().describe("Agg trade ID to start from."), - startTime: z.number().int().positive().optional().describe("Start time in ms."), - endTime: z.number().int().positive().optional().describe("End time in ms."), - limit: z.number().int().min(1).max(MAX_TRADES_LIMIT).optional() - .describe(`Number of trades. Default 500, max ${MAX_TRADES_LIMIT}.`) - }, - async ({ symbol, fromId, startTime, endTime, limit }) => { - try { - const params: Record = { symbol }; - if (fromId !== undefined) params.fromId = fromId; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const result: AggTradeResponse[] = await binanceUsRequest("GET", "/api/v3/aggTrades", params, false); - const formattedTrades = result.map(formatAggTrade); - - const firstTrade = result[0]; - const lastTrade = result[result.length - 1]; - const summary = firstTrade && lastTrade ? { - firstAggId: firstTrade.a, - lastAggId: lastTrade.a, - timeRange: `${new Date(firstTrade.T).toISOString()} to ${new Date(lastTrade.T).toISOString()}`, - latestPrice: lastTrade.p - } : null; - - return { - content: [{ - type: "text", - text: `Aggregate Trades for ${symbol}\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Total trades: ${result.length}\n` + - (summary ? `Agg ID range: ${summary.firstAggId} to ${summary.lastAggId}\n` + - `Time range: ${summary.timeRange}\n` + - `Latest price: ${summary.latestPrice}\n\n` : "\n") + - `Formatted (first 10):\n${JSON.stringify(formattedTrades.slice(0, 10), null, 2)}\n\n` + - `Raw Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + fromId: z.number().int().positive().optional().describe("Agg trade ID to start from."), + startTime: z.number().int().positive().optional().describe("Start time in ms."), + endTime: z.number().int().positive().optional().describe("End time in ms."), + limit: z + .number() + .int() + .min(1) + .max(MAX_TRADES_LIMIT) + .optional() + .describe(`Number of trades. Default 500, max ${MAX_TRADES_LIMIT}.`), + }, + }, + async ({ symbol, fromId, startTime, endTime, limit }) => { + try { + const params: Record = { symbol }; + if (fromId !== undefined) params.fromId = fromId; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const result: AggTradeResponse[] = await binanceUsRequest( + "GET", + "/api/v3/aggTrades", + params, + false, + ); + const formattedTrades = result.map(formatAggTrade); + + const firstTrade = result[0]; + const lastTrade = result[result.length - 1]; + const summary = + firstTrade && lastTrade + ? { + firstAggId: firstTrade.a, + lastAggId: lastTrade.a, + timeRange: `${new Date(firstTrade.T).toISOString()} to ${new Date(lastTrade.T).toISOString()}`, + latestPrice: lastTrade.p, + } + : null; + + return { + content: [ + { + type: "text", + text: + `Aggregate Trades for ${symbol}\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Total trades: ${result.length}\n` + + (summary + ? `Agg ID range: ${summary.firstAggId} to ${summary.lastAggId}\n` + + `Time range: ${summary.timeRange}\n` + + `Latest price: ${summary.latestPrice}\n\n` + : "\n") + + `Formatted (first 10):\n${JSON.stringify(formattedTrades.slice(0, 10), null, 2)}\n\n` + + `Raw Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_klines - Get candlestick data + server.registerTool( + "binance_us_klines", + { + description: "Get Kline/candlestick data for a trading pair. Returns OHLCV data.", + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + interval: z.enum(KLINE_INTERVALS).describe(`Kline interval: ${KLINE_INTERVALS.join(", ")}`), + startTime: z.number().int().positive().optional().describe("Start time in ms"), + endTime: z.number().int().positive().optional().describe("End time in ms"), + limit: z + .number() + .int() + .min(1) + .max(MAX_KLINES_LIMIT) + .optional() + .describe(`Number of klines. Default 500, max ${MAX_KLINES_LIMIT}.`), + }, + }, + async ({ symbol, interval, startTime, endTime, limit }) => { + try { + const params: Record = { symbol, interval }; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (limit !== undefined) params.limit = limit; + + const result: KlineRaw[] = await binanceUsRequest("GET", "/api/v3/klines", params, false); + const formattedKlines = result.map(formatKline); + + const firstKline = formattedKlines[0]; + const latestKline = formattedKlines[formattedKlines.length - 1]; + + let summaryText = ""; + if (formattedKlines.length > 0 && firstKline && latestKline) { + const highs = formattedKlines.map((k) => parseFloat(k.high)); + const lows = formattedKlines.map((k) => parseFloat(k.low)); + const volumes = formattedKlines.map((k) => parseFloat(k.volume)); + + summaryText = + `Period: ${firstKline.openTimeISO} to ${latestKline.closeTimeISO}\n` + + `Latest: O:${latestKline.open} H:${latestKline.high} L:${latestKline.low} C:${latestKline.close}\n` + + `Period High: ${Math.max(...highs)} | Period Low: ${Math.min(...lows)}\n` + + `Total Volume: ${volumes.reduce((a, b) => a + b, 0).toFixed(8)}\n`; } - ); - // binance_us_klines - Get candlestick data - server.tool( - "binance_us_klines", - "Get Kline/candlestick data for a trading pair. Returns OHLCV data.", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), - interval: z.enum(KLINE_INTERVALS).describe(`Kline interval: ${KLINE_INTERVALS.join(", ")}`), - startTime: z.number().int().positive().optional().describe("Start time in ms"), - endTime: z.number().int().positive().optional().describe("End time in ms"), - limit: z.number().int().min(1).max(MAX_KLINES_LIMIT).optional() - .describe(`Number of klines. Default 500, max ${MAX_KLINES_LIMIT}.`) - }, - async ({ symbol, interval, startTime, endTime, limit }) => { - try { - const params: Record = { symbol, interval }; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (limit !== undefined) params.limit = limit; - - const result: KlineRaw[] = await binanceUsRequest("GET", "/api/v3/klines", params, false); - const formattedKlines = result.map(formatKline); - - const firstKline = formattedKlines[0]; - const latestKline = formattedKlines[formattedKlines.length - 1]; - - let summaryText = ""; - if (formattedKlines.length > 0 && firstKline && latestKline) { - const highs = formattedKlines.map(k => parseFloat(k.high)); - const lows = formattedKlines.map(k => parseFloat(k.low)); - const volumes = formattedKlines.map(k => parseFloat(k.volume)); - - summaryText = `Period: ${firstKline.openTimeISO} to ${latestKline.closeTimeISO}\n` + - `Latest: O:${latestKline.open} H:${latestKline.high} L:${latestKline.low} C:${latestKline.close}\n` + - `Period High: ${Math.max(...highs)} | Period Low: ${Math.min(...lows)}\n` + - `Total Volume: ${volumes.reduce((a, b) => a + b, 0).toFixed(8)}\n`; - } - - return { - content: [{ - type: "text", - text: `Klines for ${symbol} (${interval})\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Total klines: ${result.length}\n` + - summaryText + "\n" + - `Formatted (last 5):\n${JSON.stringify(formattedKlines.slice(-5), null, 2)}\n\n` + - `Full Response:\n${JSON.stringify(formattedKlines, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + return { + content: [ + { + type: "text", + text: + `Klines for ${symbol} (${interval})\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Total klines: ${result.length}\n` + + summaryText + + "\n" + + `Formatted (last 5):\n${JSON.stringify(formattedKlines.slice(-5), null, 2)}\n\n` + + `Full Response:\n${JSON.stringify(formattedKlines, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_avg_price - Get average price + server.registerTool( + "binance_us_avg_price", + { + description: "Get current 5-minute rolling weighted average price.", + inputSchema: { + symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD"), + }, + }, + async ({ symbol }) => { + try { + const result = await binanceUsRequest("GET", "/api/v3/avgPrice", { symbol }, false); + + return { + content: [ + { + type: "text", + text: + `Average Price for ${symbol}\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + `Price: ${result.price}\n` + + `Window: ${result.mins} minutes\n\n` + + `Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_ticker_24hr - Get 24hr statistics + server.registerTool( + "binance_us_ticker_24hr", + { + description: "Get 24-hour rolling window price change statistics.", + inputSchema: { + symbol: z + .string() + .toUpperCase() + .optional() + .describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), + symbols: z + .array(z.string()) + .optional() + .describe("Array of symbols. Cannot use with 'symbol'."), + type: z + .enum(["FULL", "MINI"]) + .optional() + .describe("FULL (default) or MINI (fewer fields)."), + }, + }, + async ({ symbol, symbols, type }) => { + try { + if (symbol && symbols) { + return { + content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], + isError: true, + }; } - ); - // binance_us_avg_price - Get average price - server.tool( - "binance_us_avg_price", - "Get current 5-minute rolling weighted average price.", - { - symbol: z.string().toUpperCase().describe("Trading pair symbol, e.g., BTCUSD") - }, - async ({ symbol }) => { - try { - const result = await binanceUsRequest("GET", "/api/v3/avgPrice", { symbol }, false); - - return { - content: [{ - type: "text", - text: `Average Price for ${symbol}\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - `Price: ${result.price}\n` + - `Window: ${result.mins} minutes\n\n` + - `Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + const params: Record = {}; + if (symbol) params.symbol = symbol; + if (symbols?.length) params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); + if (type) params.type = type; + + const result = await binanceUsRequest("GET", "/api/v3/ticker/24hr", params, false); + + const isArray = Array.isArray(result); + let summaryText: string; + + if (isArray) { + const sorted = [...result].sort( + (a: any, b: any) => parseFloat(b.quoteVolume) - parseFloat(a.quoteVolume), + ); + const top5 = sorted.slice(0, 5); + summaryText = + `Total symbols: ${result.length}\n` + + `Top 5 by volume:\n${top5.map((t: any) => ` ${t.symbol}: ${t.priceChangePercent}% | Vol: ${parseFloat(t.quoteVolume).toLocaleString()}`).join("\n")}`; + } else { + summaryText = + `${result.symbol}: ${result.lastPrice} (${parseFloat(result.priceChangePercent) >= 0 ? "+" : ""}${result.priceChangePercent}%)\n` + + `High: ${result.highPrice} | Low: ${result.lowPrice}\n` + + `Volume: ${result.volume}`; } - ); - // binance_us_ticker_24hr - Get 24hr statistics - server.tool( - "binance_us_ticker_24hr", - "Get 24-hour rolling window price change statistics.", - { - symbol: z.string().toUpperCase().optional().describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), - symbols: z.array(z.string()).optional().describe("Array of symbols. Cannot use with 'symbol'."), - type: z.enum(["FULL", "MINI"]).optional().describe("FULL (default) or MINI (fewer fields).") - }, - async ({ symbol, symbols, type }) => { - try { - if (symbol && symbols) { - return { - content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], - isError: true - }; - } - - const params: Record = {}; - if (symbol) params.symbol = symbol; - if (symbols?.length) params.symbols = JSON.stringify(symbols.map(s => s.toUpperCase())); - if (type) params.type = type; - - const result = await binanceUsRequest("GET", "/api/v3/ticker/24hr", params, false); - - const isArray = Array.isArray(result); - let summaryText: string; - - if (isArray) { - const sorted = [...result].sort((a: any, b: any) => parseFloat(b.quoteVolume) - parseFloat(a.quoteVolume)); - const top5 = sorted.slice(0, 5); - summaryText = `Total symbols: ${result.length}\n` + - `Top 5 by volume:\n${top5.map((t: any) => ` ${t.symbol}: ${t.priceChangePercent}% | Vol: ${parseFloat(t.quoteVolume).toLocaleString()}`).join("\n")}`; - } else { - summaryText = `${result.symbol}: ${result.lastPrice} (${parseFloat(result.priceChangePercent) >= 0 ? "+" : ""}${result.priceChangePercent}%)\n` + - `High: ${result.highPrice} | Low: ${result.lowPrice}\n` + - `Volume: ${result.volume}`; - } - - return { - content: [{ - type: "text", - text: `24hr Ticker Statistics\n` + - `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - summaryText + "\n\n" + - `Full Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + return { + content: [ + { + type: "text", + text: + `24hr Ticker Statistics\n` + + `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + summaryText + + "\n\n" + + `Full Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_ticker_price - Get latest price + server.registerTool( + "binance_us_ticker_price", + { + description: "Get latest price for symbol(s).", + inputSchema: { + symbol: z + .string() + .toUpperCase() + .optional() + .describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), + symbols: z + .array(z.string()) + .optional() + .describe("Array of symbols. Cannot use with 'symbol'."), + }, + }, + async ({ symbol, symbols }) => { + try { + if (symbol && symbols) { + return { + content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], + isError: true, + }; } - ); - // binance_us_ticker_price - Get latest price - server.tool( - "binance_us_ticker_price", - "Get latest price for symbol(s).", - { - symbol: z.string().toUpperCase().optional().describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), - symbols: z.array(z.string()).optional().describe("Array of symbols. Cannot use with 'symbol'.") - }, - async ({ symbol, symbols }) => { - try { - if (symbol && symbols) { - return { - content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], - isError: true - }; - } - - const params: Record = {}; - if (symbol) params.symbol = symbol; - if (symbols?.length) params.symbols = JSON.stringify(symbols.map(s => s.toUpperCase())); - - const result = await binanceUsRequest("GET", "/api/v3/ticker/price", params, false); - - const isArray = Array.isArray(result); - const responseText = isArray - ? `Retrieved prices for ${result.length} symbols.` - : `${result.symbol}: ${result.price}`; - - return { - content: [{ - type: "text", - text: `Price Ticker\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - responseText + "\n\n" + - `Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + const params: Record = {}; + if (symbol) params.symbol = symbol; + if (symbols?.length) params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); + + const result = await binanceUsRequest("GET", "/api/v3/ticker/price", params, false); + + const isArray = Array.isArray(result); + const responseText = isArray + ? `Retrieved prices for ${result.length} symbols.` + : `${result.symbol}: ${result.price}`; + + return { + content: [ + { + type: "text", + text: + `Price Ticker\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + responseText + + "\n\n" + + `Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_ticker_book - Get book ticker + server.registerTool( + "binance_us_ticker_book", + { + description: "Get best bid/ask prices and quantities (top of book).", + inputSchema: { + symbol: z + .string() + .toUpperCase() + .optional() + .describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), + symbols: z + .array(z.string()) + .optional() + .describe("Array of symbols. Cannot use with 'symbol'."), + }, + }, + async ({ symbol, symbols }) => { + try { + if (symbol && symbols) { + return { + content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], + isError: true, + }; } - ); - // binance_us_ticker_book - Get book ticker - server.tool( - "binance_us_ticker_book", - "Get best bid/ask prices and quantities (top of book).", - { - symbol: z.string().toUpperCase().optional().describe("Symbol (e.g., BTCUSD). Cannot use with 'symbols'."), - symbols: z.array(z.string()).optional().describe("Array of symbols. Cannot use with 'symbol'.") - }, - async ({ symbol, symbols }) => { - try { - if (symbol && symbols) { - return { - content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], - isError: true - }; - } - - const params: Record = {}; - if (symbol) params.symbol = symbol; - if (symbols?.length) params.symbols = JSON.stringify(symbols.map(s => s.toUpperCase())); - - const result = await binanceUsRequest("GET", "/api/v3/ticker/bookTicker", params, false); - - const isArray = Array.isArray(result); - let summaryText: string; - - if (isArray) { - summaryText = `Total symbols: ${result.length}`; - } else { - const spread = (parseFloat(result.askPrice) - parseFloat(result.bidPrice)).toFixed(8); - const midPrice = ((parseFloat(result.askPrice) + parseFloat(result.bidPrice)) / 2).toFixed(8); - summaryText = `${result.symbol}\n` + - `Bid: ${result.bidPrice} @ ${result.bidQty}\n` + - `Ask: ${result.askPrice} @ ${result.askQty}\n` + - `Spread: ${spread} | Mid: ${midPrice}`; - } - - return { - content: [{ - type: "text", - text: `Book Ticker\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - summaryText + "\n\n" + - `Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + const params: Record = {}; + if (symbol) params.symbol = symbol; + if (symbols?.length) params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); + + const result = await binanceUsRequest("GET", "/api/v3/ticker/bookTicker", params, false); + + const isArray = Array.isArray(result); + let summaryText: string; + + if (isArray) { + summaryText = `Total symbols: ${result.length}`; + } else { + const spread = (parseFloat(result.askPrice) - parseFloat(result.bidPrice)).toFixed(8); + const midPrice = ( + (parseFloat(result.askPrice) + parseFloat(result.bidPrice)) / + 2 + ).toFixed(8); + summaryText = + `${result.symbol}\n` + + `Bid: ${result.bidPrice} @ ${result.bidQty}\n` + + `Ask: ${result.askPrice} @ ${result.askQty}\n` + + `Spread: ${spread} | Mid: ${midPrice}`; } - ); - // binance_us_rolling_window - Get rolling window stats - server.tool( - "binance_us_rolling_window", + return { + content: [ + { + type: "text", + text: + `Book Ticker\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + summaryText + + "\n\n" + + `Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); + + // binance_us_rolling_window - Get rolling window stats + server.registerTool( + "binance_us_rolling_window", + { + description: "Get rolling window price change statistics with custom window sizes (1m to 7d).", - { - symbol: z.string().toUpperCase().optional().describe("Symbol (required if 'symbols' not provided)."), - symbols: z.array(z.string()).optional().describe("Array of symbols (required if 'symbol' not provided)."), - windowSize: z.enum(ROLLING_WINDOW_SIZES).optional().describe(`Window size. Default 1d. Options: ${ROLLING_WINDOW_SIZES.join(", ")}`), - type: z.enum(["FULL", "MINI"]).optional().describe("FULL (default) or MINI.") - }, - async ({ symbol, symbols, windowSize, type }) => { - try { - if (!symbol && !symbols?.length) { - return { - content: [{ type: "text", text: "Error: Either 'symbol' or 'symbols' must be provided." }], - isError: true - }; - } - if (symbol && symbols) { - return { - content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], - isError: true - }; - } - - const params: Record = {}; - if (symbol) params.symbol = symbol; - if (symbols?.length) params.symbols = JSON.stringify(symbols.map(s => s.toUpperCase())); - if (windowSize) params.windowSize = windowSize; - if (type) params.type = type; - - const result = await binanceUsRequest("GET", "/api/v3/ticker", params, false); - - const isArray = Array.isArray(result); - const windowText = windowSize || "1d"; - let summaryText: string; - - if (isArray) { - summaryText = `Window: ${windowText}\nTotal symbols: ${result.length}`; - } else { - summaryText = `${result.symbol} (${windowText})\n` + - `Price: ${result.lastPrice} (${parseFloat(result.priceChangePercent) >= 0 ? "+" : ""}${result.priceChangePercent}%)\n` + - `High: ${result.highPrice} | Low: ${result.lowPrice}\n` + - `Volume: ${result.volume} | Trades: ${result.count}`; - } - - return { - content: [{ - type: "text", - text: `Rolling Window Statistics\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + - summaryText + "\n\n" + - `Response:\n${JSON.stringify(result, null, 2)}` - }] - }; - } catch (error) { - return formatError(error); - } + inputSchema: { + symbol: z + .string() + .toUpperCase() + .optional() + .describe("Symbol (required if 'symbols' not provided)."), + symbols: z + .array(z.string()) + .optional() + .describe("Array of symbols (required if 'symbol' not provided)."), + windowSize: z + .enum(ROLLING_WINDOW_SIZES) + .optional() + .describe(`Window size. Default 1d. Options: ${ROLLING_WINDOW_SIZES.join(", ")}`), + type: z.enum(["FULL", "MINI"]).optional().describe("FULL (default) or MINI."), + }, + }, + async ({ symbol, symbols, windowSize, type }) => { + try { + if (!symbol && !symbols?.length) { + return { + content: [ + { type: "text", text: "Error: Either 'symbol' or 'symbols' must be provided." }, + ], + isError: true, + }; + } + if (symbol && symbols) { + return { + content: [{ type: "text", text: "Error: Cannot specify both 'symbol' and 'symbols'." }], + isError: true, + }; + } + + const params: Record = {}; + if (symbol) params.symbol = symbol; + if (symbols?.length) params.symbols = JSON.stringify(symbols.map((s) => s.toUpperCase())); + if (windowSize) params.windowSize = windowSize; + if (type) params.type = type; + + const result = await binanceUsRequest("GET", "/api/v3/ticker", params, false); + + const isArray = Array.isArray(result); + const windowText = windowSize || "1d"; + let summaryText: string; + + if (isArray) { + summaryText = `Window: ${windowText}\nTotal symbols: ${result.length}`; + } else { + summaryText = + `${result.symbol} (${windowText})\n` + + `Price: ${result.lastPrice} (${parseFloat(result.priceChangePercent) >= 0 ? "+" : ""}${result.priceChangePercent}%)\n` + + `High: ${result.highPrice} | Low: ${result.lowPrice}\n` + + `Volume: ${result.volume} | Trades: ${result.count}`; } - ); + + return { + content: [ + { + type: "text", + text: + `Rolling Window Statistics\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` + + summaryText + + "\n\n" + + `Response:\n${JSON.stringify(result, null, 2)}`, + }, + ], + }; + } catch (error) { + return formatError(error); + } + }, + ); } diff --git a/src/tools/otc/index.ts b/src/tools/otc/index.ts index 3e3f0ae0..78830a38 100644 --- a/src/tools/otc/index.ts +++ b/src/tools/otc/index.ts @@ -2,23 +2,26 @@ // Binance.US OTC (Over-The-Counter) Trading Tools // Large block trades executed outside the regular order book -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Binance.US OTC trading tools - * + * * OTC trading allows large block trades to be executed outside the regular * order book, minimizing market impact for institutional traders. */ export function registerOtcTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v1/otc/coinPairs - Get Supported OTC Coin Pairs - // ===================================================================== - server.tool( - "binance_us_otc_coin_pairs", - `Get a list of supported OTC (Over-The-Counter) trading pairs on Binance.US. + // ===================================================================== + // GET /sapi/v1/otc/coinPairs - Get Supported OTC Coin Pairs + // ===================================================================== + server.registerTool( + "binance_us_otc_coin_pairs", + { + description: `Get a list of supported OTC (Over-The-Counter) trading pairs on Binance.US. OTC trading allows large block trades to be executed outside the regular order book, minimizing market impact. This endpoint returns available coin pairs with their @@ -30,39 +33,44 @@ Response includes: - toCoinMinAmount/toCoinMaxAmount: Min/max amounts for the buy coin Example: Convert large amounts of BTC to USDT without affecting market price.`, - { - fromCoin: z.string().optional().describe("Filter by source coin (e.g., BTC, SHIB)"), - toCoin: z.string().optional().describe("Filter by destination coin (e.g., USDT, KSHIB)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/otc/coinPairs", { - ...(params.fromCoin && { fromCoin: params.fromCoin.toUpperCase() }), - ...(params.toCoin && { toCoin: params.toCoin.toUpperCase() }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved OTC coin pairs. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get OTC coin pairs: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/otc/quotes - Request Quote for OTC Trade - // ===================================================================== - server.tool( - "binance_us_otc_quote", - `Request a quote for an OTC (Over-The-Counter) trade on Binance.US. + inputSchema: { + fromCoin: z.string().optional().describe("Filter by source coin (e.g., BTC, SHIB)"), + toCoin: z.string().optional().describe("Filter by destination coin (e.g., USDT, KSHIB)"), + }, + }, + async (params: { fromCoin?: string; toCoin?: string }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/otc/coinPairs", { + ...(params.fromCoin && { fromCoin: params.fromCoin.toUpperCase() }), + ...(params.toCoin && { toCoin: params.toCoin.toUpperCase() }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved OTC coin pairs. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get OTC coin pairs: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/otc/quotes - Request Quote for OTC Trade + // ===================================================================== + server.registerTool( + "binance_us_otc_quote", + { + description: `Request a quote for an OTC (Over-The-Counter) trade on Binance.US. This endpoint requests a price quote for converting one coin to another via OTC. The quote is valid for a limited time (check validTimestamp in response). @@ -81,43 +89,55 @@ Response includes: - inverseRatio: Inverse conversion ratio - validTimestamp: Unix timestamp when quote expires - toAmount/fromAmount: Calculated amounts for the trade`, - { - fromCoin: z.string().describe("Coin to sell (e.g., BTC, SHIB)"), - toCoin: z.string().describe("Coin to buy (e.g., USDT, KSHIB)"), - requestCoin: z.string().describe("Which coin's amount you're specifying (fromCoin or toCoin)"), - requestAmount: z.number().positive().describe("Amount of the request coin") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/otc/quotes", { - fromCoin: params.fromCoin.toUpperCase(), - toCoin: params.toCoin.toUpperCase(), - requestCoin: params.requestCoin.toUpperCase(), - requestAmount: params.requestAmount - }); - - return { - content: [{ - type: "text", - text: `OTC Quote received successfully. ⚠️ Quote expires at timestamp ${response.validTimestamp}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get OTC quote: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/otc/orders - Place OTC Trade Order - // ===================================================================== - server.tool( - "binance_us_otc_place_order", - `Place an OTC (Over-The-Counter) trade order using a previously acquired quote. + inputSchema: { + fromCoin: z.string().describe("Coin to sell (e.g., BTC, SHIB)"), + toCoin: z.string().describe("Coin to buy (e.g., USDT, KSHIB)"), + requestCoin: z + .string() + .describe("Which coin's amount you're specifying (fromCoin or toCoin)"), + requestAmount: z.number().positive().describe("Amount of the request coin"), + }, + }, + async (params: { + fromCoin: string; + toCoin: string; + requestCoin: string; + requestAmount: number; + }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/otc/quotes", { + fromCoin: params.fromCoin.toUpperCase(), + toCoin: params.toCoin.toUpperCase(), + requestCoin: params.requestCoin.toUpperCase(), + requestAmount: params.requestAmount, + }); + + return { + content: [ + { + type: "text", + text: `OTC Quote received successfully. ⚠️ Quote expires at timestamp ${response.validTimestamp}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get OTC quote: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/otc/orders - Place OTC Trade Order + // ===================================================================== + server.registerTool( + "binance_us_otc_place_order", + { + description: `Place an OTC (Over-The-Counter) trade order using a previously acquired quote. ⚠️ IMPORTANT: You must first call binance_us_otc_quote to get a quoteId before placing an order. The quote expires quickly, so place the order immediately after receiving the quote. @@ -132,37 +152,46 @@ Response includes: - orderId: Unique order identifier - createTime: Order creation timestamp - orderStatus: Current status of the order`, - { - quoteId: z.string().describe("Quote ID received from binance_us_otc_quote (e.g., '4e5446f2cc6f44ab86ab02abf19a2fd2')") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/otc/orders", { - quoteId: params.quoteId - }); - - return { - content: [{ - type: "text", - text: `OTC order placed successfully. Order ID: ${response.orderId}, Status: ${response.orderStatus}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to place OTC order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/otc/orders/{orderId} - Get OTC Order Details - // ===================================================================== - server.tool( - "binance_us_otc_get_order", - `Get detailed information about a specific OTC (Over-The-Counter) trade order. + inputSchema: { + quoteId: z + .string() + .describe( + "Quote ID received from binance_us_otc_quote (e.g., '4e5446f2cc6f44ab86ab02abf19a2fd2')", + ), + }, + }, + async (params: { quoteId: string }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/otc/orders", { + quoteId: params.quoteId, + }); + + return { + content: [ + { + type: "text", + text: `OTC order placed successfully. Order ID: ${response.orderId}, Status: ${response.orderStatus}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to place OTC order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/otc/orders/{orderId} - Get OTC Order Details + // ===================================================================== + server.registerTool( + "binance_us_otc_get_order", + { + description: `Get detailed information about a specific OTC (Over-The-Counter) trade order. Use this to check the status and details of a previously placed OTC order. @@ -174,35 +203,40 @@ Response includes: - toCoin/toAmount: Bought coin and amount - ratio/inverseRatio: Exchange rates - createTime: Order creation timestamp`, - { - orderId: z.string().describe("OTC order ID to query (e.g., '10002349')") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", `/sapi/v1/otc/orders/${params.orderId}`); - - return { - content: [{ - type: "text", - text: `OTC order details retrieved. Status: ${response.orderStatus}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get OTC order: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/otc/orders - Get All OTC Trade Orders - // ===================================================================== - server.tool( - "binance_us_otc_all_orders", - `Query all OTC (Over-The-Counter) trade orders with optional filters. + inputSchema: { + orderId: z.string().describe("OTC order ID to query (e.g., '10002349')"), + }, + }, + async (params: { orderId: string }) => { + try { + const response = await makeSignedRequest("GET", `/sapi/v1/otc/orders/${params.orderId}`); + + return { + content: [ + { + type: "text", + text: `OTC order details retrieved. Status: ${response.orderStatus}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get OTC order: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/otc/orders - Get All OTC Trade Orders + // ===================================================================== + server.registerTool( + "binance_us_otc_all_orders", + { + description: `Query all OTC (Over-The-Counter) trade orders with optional filters. Use this to retrieve your OTC trading history with various filtering options. @@ -212,49 +246,68 @@ Response includes: Each order contains: quoteId, orderId, orderStatus, fromCoin, fromAmount, toCoin, toAmount, ratio, inverseRatio, createTime`, - { - orderId: z.string().optional().describe("Filter by specific order ID"), - fromCoin: z.string().optional().describe("Filter by source coin (e.g., BTC, KSHIB)"), - toCoin: z.string().optional().describe("Filter by destination coin (e.g., USDT, SHIB)"), - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - page: z.number().int().positive().optional().describe("Page number (starts from 1)"), - limit: z.number().int().min(1).max(100).optional().describe("Records per page (default: 10, max: 100)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/otc/orders", { - ...(params.orderId && { orderId: params.orderId }), - ...(params.fromCoin && { fromCoin: params.fromCoin.toUpperCase() }), - ...(params.toCoin && { toCoin: params.toCoin.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${response.total} OTC orders. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get OTC orders: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/ocbs/orders - Get All OCBS (Fiat) Orders - // ===================================================================== - server.tool( - "binance_us_ocbs_orders", - `Query all OCBS (One-Click-Buy-Sell) fiat orders on Binance.US. + inputSchema: { + orderId: z.string().optional().describe("Filter by specific order ID"), + fromCoin: z.string().optional().describe("Filter by source coin (e.g., BTC, KSHIB)"), + toCoin: z.string().optional().describe("Filter by destination coin (e.g., USDT, SHIB)"), + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + page: z.number().int().positive().optional().describe("Page number (starts from 1)"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Records per page (default: 10, max: 100)"), + }, + }, + async (params: { + orderId?: string; + fromCoin?: string; + toCoin?: string; + startTime?: number; + endTime?: number; + page?: number; + limit?: number; + }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/otc/orders", { + ...(params.orderId && { orderId: params.orderId }), + ...(params.fromCoin && { fromCoin: params.fromCoin.toUpperCase() }), + ...(params.toCoin && { toCoin: params.toCoin.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${response.total} OTC orders. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get OTC orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/ocbs/orders - Get All OCBS (Fiat) Orders + // ===================================================================== + server.registerTool( + "binance_us_ocbs_orders", + { + description: `Query all OCBS (One-Click-Buy-Sell) fiat orders on Binance.US. OCBS allows direct fiat-to-crypto conversions. This endpoint retrieves your OCBS order history for fiat transactions (e.g., USD to BTC). @@ -270,36 +323,52 @@ Each order contains: - feeCoin/feeAmount: Fee details - ratio: Exchange rate - createTime: Order timestamp`, - { - orderId: z.string().optional().describe("Filter by specific order ID"), - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - page: z.number().int().positive().optional().describe("Page number (starts from 1)"), - limit: z.number().int().min(1).max(100).optional().describe("Records per page (default: 10, max: 100)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/ocbs/orders", { - ...(params.orderId && { orderId: params.orderId }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Retrieved ${response.total} OCBS orders. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get OCBS orders: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + orderId: z.string().optional().describe("Filter by specific order ID"), + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + page: z.number().int().positive().optional().describe("Page number (starts from 1)"), + limit: z + .number() + .int() + .min(1) + .max(100) + .optional() + .describe("Records per page (default: 10, max: 100)"), + }, + }, + async (params: { + orderId?: string; + startTime?: number; + endTime?: number; + page?: number; + limit?: number; + }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/ocbs/orders", { + ...(params.orderId && { orderId: params.orderId }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Retrieved ${response.total} OCBS orders. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get OCBS orders: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/staking/index.ts b/src/tools/staking/index.ts index 1e7ebad1..e900be26 100644 --- a/src/tools/staking/index.ts +++ b/src/tools/staking/index.ts @@ -2,23 +2,26 @@ // Binance.US Staking Tools // Earn rewards by staking supported cryptocurrencies -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Binance.US Staking tools - * + * * Staking allows users to earn rewards by locking up their cryptocurrency * to support network operations. Binance.US offers staking for various assets. */ export function registerStakingTools(server: McpServer) { - // ===================================================================== - // GET /sapi/v1/staking/asset - Get Staking Asset Information - // ===================================================================== - server.tool( - "binance_us_staking_asset_info", - `Get staking information for supported assets on Binance.US. + // ===================================================================== + // GET /sapi/v1/staking/asset - Get Staking Asset Information + // ===================================================================== + server.registerTool( + "binance_us_staking_asset_info", + { + description: `Get staking information for supported assets on Binance.US. Returns details about staking options including APR, APY, and staking limits. @@ -33,37 +36,45 @@ Response includes for each asset: - autoRestake: Whether rewards are automatically restaked If no asset is specified, returns information for all staking assets.`, - { - stakingAsset: z.string().optional().describe("Asset symbol (e.g., BNB, ETH). If empty, returns all staking assets") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/staking/asset", { - ...(params.stakingAsset && { stakingAsset: params.stakingAsset.toUpperCase() }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved staking asset information. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get staking asset info: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/staking/stake - Stake Asset - // ===================================================================== - server.tool( - "binance_us_staking_stake", - `Stake a supported asset on Binance.US to earn staking rewards. + inputSchema: { + stakingAsset: z + .string() + .optional() + .describe("Asset symbol (e.g., BNB, ETH). If empty, returns all staking assets"), + }, + }, + async (params: { stakingAsset?: string }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/staking/asset", { + ...(params.stakingAsset && { stakingAsset: params.stakingAsset.toUpperCase() }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved staking asset information. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get staking asset info: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/staking/stake - Stake Asset + // ===================================================================== + server.registerTool( + "binance_us_staking_stake", + { + description: `Stake a supported asset on Binance.US to earn staking rewards. ⚠️ IMPORTANT: - Staking locks your assets for a period of time @@ -79,41 +90,50 @@ Parameters: Response includes: - result: SUCCESS or failure status - purchaseRecordId: Record ID for the staking transaction`, - { - stakingAsset: z.string().describe("Asset symbol to stake (e.g., BNB, ETH)"), - amount: z.number().positive().describe("Amount to stake"), - autoRestake: z.boolean().optional().default(true).describe("Automatically restake rewards (default: true)") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/staking/stake", { - stakingAsset: params.stakingAsset.toUpperCase(), - amount: params.amount, - autoRestake: params.autoRestake - }); - - return { - content: [{ - type: "text", - text: `Staking request submitted. Result: ${response.data?.result || response.result}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to stake asset: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // POST /sapi/v1/staking/unstake - Unstake Asset - // ===================================================================== - server.tool( - "binance_us_staking_unstake", - `Unstake a previously staked asset on Binance.US. + inputSchema: { + stakingAsset: z.string().describe("Asset symbol to stake (e.g., BNB, ETH)"), + amount: z.number().positive().describe("Amount to stake"), + autoRestake: z + .boolean() + .optional() + .default(true) + .describe("Automatically restake rewards (default: true)"), + }, + }, + async (params: { stakingAsset: string; amount: number; autoRestake?: boolean }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/staking/stake", { + stakingAsset: params.stakingAsset.toUpperCase(), + amount: params.amount, + autoRestake: params.autoRestake, + }); + + return { + content: [ + { + type: "text", + text: `Staking request submitted. Result: ${response.data?.result || response.result}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to stake asset: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // POST /sapi/v1/staking/unstake - Unstake Asset + // ===================================================================== + server.registerTool( + "binance_us_staking_unstake", + { + description: `Unstake a previously staked asset on Binance.US. ⚠️ IMPORTANT: - Unstaking may take time (check unstakingPeriod in asset info) @@ -126,39 +146,44 @@ Parameters: Response includes: - result: SUCCESS or failure status`, - { - stakingAsset: z.string().describe("Asset symbol to unstake (e.g., BNB, ETH)"), - amount: z.number().positive().describe("Amount to unstake") - }, - async (params) => { - try { - const response = await makeSignedRequest("POST", "/sapi/v1/staking/unstake", { - stakingAsset: params.stakingAsset.toUpperCase(), - amount: params.amount - }); - - return { - content: [{ - type: "text", - text: `Unstaking request submitted. Result: ${response.data?.result || response.result}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to unstake asset: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/staking/stakingBalance - Get Staking Balance - // ===================================================================== - server.tool( - "binance_us_staking_balance", - `Get current staking balance for assets on Binance.US. + inputSchema: { + stakingAsset: z.string().describe("Asset symbol to unstake (e.g., BNB, ETH)"), + amount: z.number().positive().describe("Amount to unstake"), + }, + }, + async (params: { stakingAsset: string; amount: number }) => { + try { + const response = await makeSignedRequest("POST", "/sapi/v1/staking/unstake", { + stakingAsset: params.stakingAsset.toUpperCase(), + amount: params.amount, + }); + + return { + content: [ + { + type: "text", + text: `Unstaking request submitted. Result: ${response.data?.result || response.result}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to unstake asset: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/staking/stakingBalance - Get Staking Balance + // ===================================================================== + server.registerTool( + "binance_us_staking_balance", + { + description: `Get current staking balance for assets on Binance.US. Returns your current staking positions and their details. @@ -171,37 +196,45 @@ Response includes for each staked asset: - autoRestake: Whether auto-restaking is enabled If no asset is specified, returns balances for all staked assets.`, - { - asset: z.string().optional().describe("Staked asset symbol. If empty, returns all assets with balances") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/staking/stakingBalance", { - ...(params.asset && { asset: params.asset.toUpperCase() }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved staking balance. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get staking balance: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/staking/history - Get Staking History - // ===================================================================== - server.tool( - "binance_us_staking_history", - `Get staking transaction history for assets on Binance.US. + inputSchema: { + asset: z + .string() + .optional() + .describe("Staked asset symbol. If empty, returns all assets with balances"), + }, + }, + async (params: { asset?: string }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/staking/stakingBalance", { + ...(params.asset && { asset: params.asset.toUpperCase() }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved staking balance. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get staking balance: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/staking/history - Get Staking History + // ===================================================================== + server.registerTool( + "binance_us_staking_history", + { + description: `Get staking transaction history for assets on Binance.US. Returns a history of staking and unstaking transactions. @@ -213,45 +246,72 @@ Response includes for each transaction: - status: Transaction status (SUCCESS, PENDING, etc.) If no asset is specified, returns history for all assets.`, - { - asset: z.string().optional().describe("Asset symbol. If empty, returns all assets with history"), - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - page: z.number().int().positive().optional().default(1).describe("Page number (default: 1)"), - limit: z.number().int().min(1).max(500).optional().default(500).describe("Records per page (default: 500, max: 500)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/staking/history", { - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved staking history. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get staking history: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // GET /sapi/v1/staking/stakingRewardsHistory - Get Staking Rewards History - // ===================================================================== - server.tool( - "binance_us_staking_rewards", - `Get staking rewards history for assets on Binance.US. + inputSchema: { + asset: z + .string() + .optional() + .describe("Asset symbol. If empty, returns all assets with history"), + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + page: z + .number() + .int() + .positive() + .optional() + .default(1) + .describe("Page number (default: 1)"), + limit: z + .number() + .int() + .min(1) + .max(500) + .optional() + .default(500) + .describe("Records per page (default: 500, max: 500)"), + }, + }, + async (params: { + asset?: string; + startTime?: number; + endTime?: number; + page?: number; + limit?: number; + }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/staking/history", { + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved staking history. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get staking history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // GET /sapi/v1/staking/stakingRewardsHistory - Get Staking Rewards History + // ===================================================================== + server.registerTool( + "binance_us_staking_rewards", + { + description: `Get staking rewards history for assets on Binance.US. Returns a history of staking rewards earned over time. @@ -268,36 +328,58 @@ Each reward record contains: - autoRestaked: Whether the reward was automatically restaked If no asset is specified, returns rewards for all staked assets.`, - { - asset: z.string().optional().describe("Staked asset. If empty, returns all assets with rewards"), - startTime: z.number().optional().describe("Start timestamp in milliseconds"), - endTime: z.number().optional().describe("End timestamp in milliseconds"), - page: z.number().int().positive().optional().describe("Page/batch number"), - limit: z.number().int().min(1).max(500).optional().default(500).describe("Records per batch (default: 500)") - }, - async (params) => { - try { - const response = await makeSignedRequest("GET", "/sapi/v1/staking/stakingRewardsHistory", { - ...(params.asset && { asset: params.asset.toUpperCase() }), - ...(params.startTime && { startTime: params.startTime }), - ...(params.endTime && { endTime: params.endTime }), - ...(params.page && { page: params.page }), - ...(params.limit && { limit: params.limit }) - }); - - return { - content: [{ - type: "text", - text: `Successfully retrieved staking rewards history. Total: ${response.total || 'N/A'}. Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get staking rewards history: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + asset: z + .string() + .optional() + .describe("Staked asset. If empty, returns all assets with rewards"), + startTime: z.number().optional().describe("Start timestamp in milliseconds"), + endTime: z.number().optional().describe("End timestamp in milliseconds"), + page: z.number().int().positive().optional().describe("Page/batch number"), + limit: z + .number() + .int() + .min(1) + .max(500) + .optional() + .default(500) + .describe("Records per batch (default: 500)"), + }, + }, + async (params: { + asset?: string; + startTime?: number; + endTime?: number; + page?: number; + limit?: number; + }) => { + try { + const response = await makeSignedRequest("GET", "/sapi/v1/staking/stakingRewardsHistory", { + ...(params.asset && { asset: params.asset.toUpperCase() }), + ...(params.startTime && { startTime: params.startTime }), + ...(params.endTime && { endTime: params.endTime }), + ...(params.page && { page: params.page }), + ...(params.limit && { limit: params.limit }), + }); + + return { + content: [ + { + type: "text", + text: `Successfully retrieved staking rewards history. Total: ${response.total || "N/A"}. Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [ + { type: "text", text: `Failed to get staking rewards history: ${errorMessage}` }, + ], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/subaccount/index.ts b/src/tools/subaccount/index.ts index 4c29ea44..1275257f 100644 --- a/src/tools/subaccount/index.ts +++ b/src/tools/subaccount/index.ts @@ -1,11 +1,13 @@ // src/tools/subaccount/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Sub-account related tools for Binance.US - * + * * Sub-account endpoints provide access to: * - List sub-accounts * - Transfer history between accounts @@ -15,243 +17,280 @@ import { makeSignedRequest } from "../../config/binanceUsClient.js"; * - Sub-account status */ export function registerSubaccountTools(server: McpServer) { - // ===================================================== - // binance_us_subaccount_list - // GET /sapi/v3/sub-account/list - // ===================================================== - server.tool( - "binance_us_subaccount_list", - "Get a list of all sub-accounts. Filter by email or status (enabled/disabled).", - { - email: z.string().optional().describe("Filter by sub-account email"), - status: z.string().optional().describe("Filter by status: 'enabled' or 'disabled'"), - page: z.number().optional().describe("Page number. Default: 1"), - limit: z.number().optional().describe("Results per page. Default: 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ email, status, page, limit, recvWindow }) => { - try { - const params: Record = {}; - if (email !== undefined) params.email = email; - if (status !== undefined) params.status = status; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v3/sub-account/list", params); - - return { - content: [{ - type: "text", - text: `Sub-accounts:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get sub-account list: ${errorMessage}` }], - isError: true - }; - } - } - ); + // ===================================================== + // binance_us_subaccount_list + // GET /sapi/v3/sub-account/list + // ===================================================== + server.registerTool( + "binance_us_subaccount_list", + { + description: "Get a list of all sub-accounts. Filter by email or status (enabled/disabled).", + inputSchema: { + email: z.string().optional().describe("Filter by sub-account email"), + status: z.string().optional().describe("Filter by status: 'enabled' or 'disabled'"), + page: z.number().optional().describe("Page number. Default: 1"), + limit: z.number().optional().describe("Results per page. Default: 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, status, page, limit, recvWindow }) => { + try { + const params: Record = {}; + if (email !== undefined) params.email = email; + if (status !== undefined) params.status = status; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v3/sub-account/list", params); + + return { + content: [ + { + type: "text", + text: `Sub-accounts:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get sub-account list: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_subaccount_transfer_history + // GET /sapi/v3/sub-account/transfer/history + // ===================================================== + server.registerTool( + "binance_us_subaccount_transfer_history", + { + description: "Get transfer history between master and sub-accounts.", + inputSchema: { + email: z.string().optional().describe("Sub-account email to filter by"), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + page: z.number().optional().describe("Page number. Each page contains up to 500 records"), + limit: z.number().optional().describe("Results per page. Default: 500"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, startTime, endTime, page, limit, recvWindow }) => { + try { + const params: Record = {}; + if (email !== undefined) params.email = email; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (page !== undefined) params.page = page; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; - // ===================================================== - // binance_us_subaccount_transfer_history - // GET /sapi/v3/sub-account/transfer/history - // ===================================================== - server.tool( - "binance_us_subaccount_transfer_history", - "Get transfer history between master and sub-accounts.", - { - email: z.string().optional().describe("Sub-account email to filter by"), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - page: z.number().optional().describe("Page number. Each page contains up to 500 records"), - limit: z.number().optional().describe("Results per page. Default: 500"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ email, startTime, endTime, page, limit, recvWindow }) => { - try { - const params: Record = {}; - if (email !== undefined) params.email = email; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (page !== undefined) params.page = page; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v3/sub-account/transfer/history", params); - - return { - content: [{ - type: "text", - text: `Sub-account Transfer History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], - isError: true - }; - } - } - ); + const data = await makeSignedRequest( + "GET", + "/sapi/v3/sub-account/transfer/history", + params, + ); - // ===================================================== - // binance_us_subaccount_transfer - // POST /sapi/v3/sub-account/transfer - // ===================================================== - server.tool( - "binance_us_subaccount_transfer", + return { + content: [ + { + type: "text", + text: `Sub-account Transfer History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get transfer history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_subaccount_transfer + // POST /sapi/v3/sub-account/transfer + // ===================================================== + server.registerTool( + "binance_us_subaccount_transfer", + { + description: "Execute an asset transfer between master account and a sub-account. ⚠️ This moves funds between accounts!", - { - fromEmail: z.string().email().describe("Sender email address"), - toEmail: z.string().email().describe("Recipient email address"), - asset: z.string().describe("Asset symbol to transfer, e.g., BTC, ETH"), - amount: z.number().describe("Amount to transfer"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ fromEmail, toEmail, asset, amount, recvWindow }) => { - try { - const params: Record = { - fromEmail, - toEmail, - asset, - amount - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("POST", "/sapi/v3/sub-account/transfer", params); - - return { - content: [{ - type: "text", - text: `Transfer completed successfully!\nTransaction ID: ${data.txnId}\nFrom: ${fromEmail}\nTo: ${toEmail}\nAsset: ${asset}\nAmount: ${amount}\n\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + fromEmail: z.string().email().describe("Sender email address"), + toEmail: z.string().email().describe("Recipient email address"), + asset: z.string().describe("Asset symbol to transfer, e.g., BTC, ETH"), + amount: z.number().describe("Amount to transfer"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ fromEmail, toEmail, asset, amount, recvWindow }) => { + try { + const params: Record = { + fromEmail, + toEmail, + asset, + amount, + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("POST", "/sapi/v3/sub-account/transfer", params); + + return { + content: [ + { + type: "text", + text: `Transfer completed successfully!\nTransaction ID: ${data.txnId}\nFrom: ${fromEmail}\nTo: ${toEmail}\nAsset: ${asset}\nAmount: ${amount}\n\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to execute transfer: ${errorMessage}` }], + isError: true, + }; + } + }, + ); - // ===================================================== - // binance_us_subaccount_assets - // GET /sapi/v3/sub-account/assets - // ===================================================== - server.tool( - "binance_us_subaccount_assets", - "Get asset balances for a specific sub-account.", - { - email: z.string().email().describe("Sub-account email address"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ email, recvWindow }) => { - try { - const params: Record = { email }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v3/sub-account/assets", params); - - // Filter to show only non-zero balances - const nonZeroBalances = data.balances?.filter( - (b: { free: string | number; locked: string | number }) => - parseFloat(String(b.free)) > 0 || parseFloat(String(b.locked)) > 0 - ) || []; - - return { - content: [{ - type: "text", - text: `Sub-account Assets for ${email}:\n\nNon-zero balances:\n${JSON.stringify(nonZeroBalances, null, 2)}\n\nFull response:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get sub-account assets: ${errorMessage}` }], - isError: true - }; - } - } - ); + // ===================================================== + // binance_us_subaccount_assets + // GET /sapi/v3/sub-account/assets + // ===================================================== + server.registerTool( + "binance_us_subaccount_assets", + { + description: "Get asset balances for a specific sub-account.", + inputSchema: { + email: z.string().email().describe("Sub-account email address"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: Record = { email }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; - // ===================================================== - // binance_us_subaccount_summary - // GET /sapi/v1/sub-account/spotSummary - // ===================================================== - server.tool( - "binance_us_subaccount_summary", - "Get the total USD value of assets in the master account and all sub-accounts.", - { - email: z.string().optional().describe("Filter by specific sub-account email"), - page: z.number().optional().describe("Page number"), - size: z.number().optional().describe("Results per page"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ email, page, size, recvWindow }) => { - try { - const params: Record = {}; - if (email !== undefined) params.email = email; - if (page !== undefined) params.page = page; - if (size !== undefined) params.size = size; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/sub-account/spotSummary", params); - - return { - content: [{ - type: "text", - text: `Sub-account Summary:\nTotal Accounts: ${data.totalCount}\nMaster Account Total Asset (USD): ${data.masterAccountTotalAsset}\n\nSub-account Details:\n${JSON.stringify(data.spotSubUserAssetBtcVoList, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get sub-account summary: ${errorMessage}` }], - isError: true - }; - } - } - ); + const data = await makeSignedRequest("GET", "/sapi/v3/sub-account/assets", params); - // ===================================================== - // binance_us_subaccount_status - // GET /sapi/v1/sub-account/status - // ===================================================== - server.tool( - "binance_us_subaccount_status", + // Filter to show only non-zero balances + const nonZeroBalances = + data.balances?.filter( + (b: { free: string | number; locked: string | number }) => + parseFloat(String(b.free)) > 0 || parseFloat(String(b.locked)) > 0, + ) || []; + + return { + content: [ + { + type: "text", + text: `Sub-account Assets for ${email}:\n\nNon-zero balances:\n${JSON.stringify(nonZeroBalances, null, 2)}\n\nFull response:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get sub-account assets: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_subaccount_summary + // GET /sapi/v1/sub-account/spotSummary + // ===================================================== + server.registerTool( + "binance_us_subaccount_summary", + { + description: "Get the total USD value of assets in the master account and all sub-accounts.", + inputSchema: { + email: z.string().optional().describe("Filter by specific sub-account email"), + page: z.number().optional().describe("Page number"), + size: z.number().optional().describe("Results per page"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, page, size, recvWindow }) => { + try { + const params: Record = {}; + if (email !== undefined) params.email = email; + if (page !== undefined) params.page = page; + if (size !== undefined) params.size = size; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/sub-account/spotSummary", params); + + return { + content: [ + { + type: "text", + text: `Sub-account Summary:\nTotal Accounts: ${data.totalCount}\nMaster Account Total Asset (USD): ${data.masterAccountTotalAsset}\n\nSub-account Details:\n${JSON.stringify(data.spotSubUserAssetBtcVoList, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get sub-account summary: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_subaccount_status + // GET /sapi/v1/sub-account/status + // ===================================================== + server.registerTool( + "binance_us_subaccount_status", + { + description: "Get status list of sub-accounts including activation status and enabled features.", - { - email: z.string().optional().describe("Sub-account email to check status for"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ email, recvWindow }) => { - try { - const params: Record = {}; - if (email !== undefined) params.email = email; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/sub-account/status", params); - - return { - content: [{ - type: "text", - text: `Sub-account Status:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get sub-account status: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + email: z.string().optional().describe("Sub-account email to check status for"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ email, recvWindow }) => { + try { + const params: Record = {}; + if (email !== undefined) params.email = email; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/sub-account/status", params); + + return { + content: [ + { + type: "text", + text: `Sub-account Status:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get sub-account status: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/tools/trade/index.ts b/src/tools/trade/index.ts index 12452206..1627c762 100644 --- a/src/tools/trade/index.ts +++ b/src/tools/trade/index.ts @@ -1,11 +1,12 @@ // src/tools/trade/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { registerBinanceUsOrderTools } from "./orders.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { registerBinanceUsOcoTools } from "./oco.js"; +import { registerBinanceUsOrderTools } from "./orders.js"; /** * Register all Binance.US trading tools - * + * * Standard Order Tools (8 tools): * - binance_us_new_order: Place new order * - binance_us_test_order: Test order (no execution) @@ -15,7 +16,7 @@ import { registerBinanceUsOcoTools } from "./oco.js"; * - binance_us_cancel_all_open_orders: Cancel all open orders for a symbol * - binance_us_open_orders: Get all open orders * - binance_us_all_orders: Get all orders (history) - * + * * OCO Order Tools (5 tools): * - binance_us_new_oco: Place OCO order * - binance_us_get_oco: Query OCO order @@ -24,8 +25,8 @@ import { registerBinanceUsOcoTools } from "./oco.js"; * - binance_us_all_oco_orders: Get OCO order history */ export function registerBinanceUsTradeTools(server: McpServer) { - registerBinanceUsOrderTools(server); - registerBinanceUsOcoTools(server); + registerBinanceUsOrderTools(server); + registerBinanceUsOcoTools(server); } // Re-export individual registration functions for granular control @@ -34,20 +35,20 @@ export { registerBinanceUsOcoTools } from "./oco.js"; // Re-export individual tool registration functions export { - registerBinanceUsNewOrder, - registerBinanceUsTestOrder, - registerBinanceUsGetOrder, - registerBinanceUsCancelOrder, - registerBinanceUsCancelReplace, - registerBinanceUsCancelAllOpenOrders, - registerBinanceUsOpenOrders, - registerBinanceUsAllOrders + registerBinanceUsNewOrder, + registerBinanceUsTestOrder, + registerBinanceUsGetOrder, + registerBinanceUsCancelOrder, + registerBinanceUsCancelReplace, + registerBinanceUsCancelAllOpenOrders, + registerBinanceUsOpenOrders, + registerBinanceUsAllOrders, } from "./orders.js"; export { - registerBinanceUsNewOco, - registerBinanceUsGetOco, - registerBinanceUsCancelOco, - registerBinanceUsOpenOco, - registerBinanceUsAllOcoOrders + registerBinanceUsNewOco, + registerBinanceUsGetOco, + registerBinanceUsCancelOco, + registerBinanceUsOpenOco, + registerBinanceUsAllOcoOrders, } from "./oco.js"; diff --git a/src/tools/trade/oco.ts b/src/tools/trade/oco.ts index 4d8df98f..caf549fb 100644 --- a/src/tools/trade/oco.ts +++ b/src/tools/trade/oco.ts @@ -1,65 +1,74 @@ // src/tools/trade/oco.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; -import { makeSignedRequest, hasApiCredentials, BINANCE_US_CONFIG } from "../../config/binanceUsClient.js"; + +import { + BINANCE_US_CONFIG, + hasApiCredentials, + makeSignedRequest, +} from "../../config/binanceUsClient.js"; // Common Binance error codes for better error messages const BINANCE_ERROR_CODES: Record = { - [-1000]: "Unknown error occurred", - [-1002]: "Unauthorized - check API key permissions", - [-1003]: "Too many requests - rate limit exceeded", - [-1013]: "Invalid quantity - check LOT_SIZE filter", - [-1021]: "Invalid timestamp - check recvWindow", - [-1022]: "Invalid signature", - [-1102]: "Mandatory parameter missing", - [-1111]: "Precision over maximum for asset", - [-1121]: "Invalid symbol", - [-2010]: "New order rejected", - [-2011]: "Cancel rejected - check order status", - [-2013]: "Order does not exist", - [-2015]: "Rejected - invalid API key, IP, or permissions", - [-2018]: "Balance is insufficient", - [-2021]: "Order would immediately trigger stop price" + [-1000]: "Unknown error occurred", + [-1002]: "Unauthorized - check API key permissions", + [-1003]: "Too many requests - rate limit exceeded", + [-1013]: "Invalid quantity - check LOT_SIZE filter", + [-1021]: "Invalid timestamp - check recvWindow", + [-1022]: "Invalid signature", + [-1102]: "Mandatory parameter missing", + [-1111]: "Precision over maximum for asset", + [-1121]: "Invalid symbol", + [-2010]: "New order rejected", + [-2011]: "Cancel rejected - check order status", + [-2013]: "Order does not exist", + [-2015]: "Rejected - invalid API key, IP, or permissions", + [-2018]: "Balance is insufficient", + [-2021]: "Order would immediately trigger stop price", }; /** * Get human-readable error message for Binance error code */ function getBinanceErrorMessage(code: number): string { - return BINANCE_ERROR_CODES[code] || `Unknown error code: ${code}`; + return BINANCE_ERROR_CODES[code] || `Unknown error code: ${code}`; } /** * Check API credentials before making requests */ function checkCredentials(): string | null { - if (!hasApiCredentials()) { - return "❌ API credentials not configured. Please set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables."; - } - return null; + if (!hasApiCredentials()) { + return "❌ API credentials not configured. Please set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables."; + } + + return null; } /** * Validate recvWindow parameter */ function validateRecvWindow(recvWindow?: number): string | null { - if (recvWindow !== undefined && recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { - return `❌ recvWindow cannot exceed ${BINANCE_US_CONFIG.MAX_RECV_WINDOW}ms (60 seconds).`; - } - return null; + if (recvWindow !== undefined && recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { + return `❌ recvWindow cannot exceed ${BINANCE_US_CONFIG.MAX_RECV_WINDOW}ms (60 seconds).`; + } + + return null; } /** * Validate symbol format (basic check) */ function validateSymbol(symbol: string): string | null { - if (!symbol || symbol.length < 2 || symbol.length > 20) { - return "❌ Invalid symbol format. Symbol should be 2-20 characters (e.g., BTCUSD, ETHUSD)."; - } - if (!/^[A-Z0-9]+$/.test(symbol.toUpperCase())) { - return "❌ Invalid symbol format. Symbol should contain only letters and numbers."; - } - return null; + if (!symbol || symbol.length < 2 || symbol.length > 20) { + return "❌ Invalid symbol format. Symbol should be 2-20 characters (e.g., BTCUSD, ETHUSD)."; + } + if (!/^[A-Z0-9]+$/.test(symbol.toUpperCase())) { + return "❌ Invalid symbol format. Symbol should contain only letters and numbers."; + } + + return null; } // Order side enum @@ -78,404 +87,552 @@ const SelfTradePreventionMode = z.enum(["EXPIRE_TAKER", "EXPIRE_MAKER", "EXPIRE_ * Register new OCO order tool */ export function registerBinanceUsNewOco(server: McpServer) { - server.tool( - "binance_us_new_oco", + server.registerTool( + "binance_us_new_oco", + { + description: "Place a new OCO (One-Cancels-the-Other) order on Binance.US. OCO orders combine a limit order with a stop-loss order. When one triggers, the other is automatically cancelled. Note: For SELL OCOs, limit price > stop price. For BUY OCOs, limit price < stop price.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), - side: OrderSide.describe("Order side: BUY or SELL"), - quantity: z.number().describe("Order quantity for both legs of the OCO"), - price: z.number().describe("Limit order price"), - stopPrice: z.number().describe("Stop price that triggers the stop-loss order"), - stopLimitPrice: z.number().optional().describe("Limit price for the stop-loss leg. If provided, stopLimitTimeInForce is required."), - stopLimitTimeInForce: TimeInForce.optional().describe("Time in force for stop-limit order: GTC, IOC, or FOK. Required if stopLimitPrice is provided."), - listClientOrderId: z.string().optional().describe("Unique ID for the entire OCO order list"), - limitClientOrderId: z.string().optional().describe("Unique ID for the limit order leg"), - stopClientOrderId: z.string().optional().describe("Unique ID for the stop-loss leg"), - limitIcebergQty: z.number().optional().describe("Iceberg quantity for the limit leg"), - stopIcebergQty: z.number().optional().describe("Iceberg quantity for the stop-loss leg"), - trailingDelta: z.number().optional().describe("Trailing delta in BIPS for the stop leg"), - newOrderRespType: OrderRespType.optional().describe("Response type: ACK, RESULT, or FULL"), - selfTradePreventionMode: SelfTradePreventionMode.optional().describe("Self-trade prevention mode"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - // Validate OCO parameters - const validationError = validateOcoParams(params); - if (validationError) { - return { - content: [{ type: "text", text: validationError }], - isError: true - }; - } - - const response = await makeSignedRequest("POST", "/api/v3/order/oco", params); - - const orders = response.orders || []; - const orderReports = response.orderReports || []; - - return { - content: [{ - type: "text", - text: `✅ OCO Order placed successfully!\n\n` + - `Order List ID: ${response.orderListId}\n` + - `Symbol: ${response.symbol}\n` + - `Status: ${response.listStatusType}\n` + - `Contingency Type: ${response.contingencyType}\n` + - `\n--- Orders ---\n` + - orders.map((order: any) => - `• Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}` - ).join('\n') + - `\n\n--- Order Details ---\n` + - orderReports.map((report: any) => - `• ${report.type} | Side: ${report.side} | ` + - `Qty: ${report.origQty} @ ${report.price} | ` + - `Status: ${report.status}` + - (report.stopPrice ? ` | Stop: ${report.stopPrice}` : '') - ).join('\n') + - `\n\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to place OCO order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), + side: OrderSide.describe("Order side: BUY or SELL"), + quantity: z.number().describe("Order quantity for both legs of the OCO"), + price: z.number().describe("Limit order price"), + stopPrice: z.number().describe("Stop price that triggers the stop-loss order"), + stopLimitPrice: z + .number() + .optional() + .describe( + "Limit price for the stop-loss leg. If provided, stopLimitTimeInForce is required.", + ), + stopLimitTimeInForce: TimeInForce.optional().describe( + "Time in force for stop-limit order: GTC, IOC, or FOK. Required if stopLimitPrice is provided.", + ), + listClientOrderId: z + .string() + .optional() + .describe("Unique ID for the entire OCO order list"), + limitClientOrderId: z.string().optional().describe("Unique ID for the limit order leg"), + stopClientOrderId: z.string().optional().describe("Unique ID for the stop-loss leg"), + limitIcebergQty: z.number().optional().describe("Iceberg quantity for the limit leg"), + stopIcebergQty: z.number().optional().describe("Iceberg quantity for the stop-loss leg"), + trailingDelta: z.number().optional().describe("Trailing delta in BIPS for the stop leg"), + newOrderRespType: OrderRespType.optional().describe("Response type: ACK, RESULT, or FULL"), + selfTradePreventionMode: SelfTradePreventionMode.optional().describe( + "Self-trade prevention mode", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + // Validate OCO parameters + const validationError = validateOcoParams(params); + if (validationError) { + return { + content: [{ type: "text", text: validationError }], + isError: true, + }; } - ); + + const response = await makeSignedRequest("POST", "/api/v3/order/oco", params); + + const orders = response.orders || []; + const orderReports = response.orderReports || []; + + return { + content: [ + { + type: "text", + text: + `✅ OCO Order placed successfully!\n\n` + + `Order List ID: ${response.orderListId}\n` + + `Symbol: ${response.symbol}\n` + + `Status: ${response.listStatusType}\n` + + `Contingency Type: ${response.contingencyType}\n` + + `\n--- Orders ---\n` + + orders + .map( + (order: any) => + `• Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}`, + ) + .join("\n") + + `\n\n--- Order Details ---\n` + + orderReports + .map( + (report: any) => + `• ${report.type} | Side: ${report.side} | ` + + `Qty: ${report.origQty} @ ${report.price} | ` + + `Status: ${report.status}` + + (report.stopPrice ? ` | Stop: ${report.stopPrice}` : ""), + ) + .join("\n") + + `\n\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to place OCO order: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register get OCO order tool */ export function registerBinanceUsGetOco(server: McpServer) { - server.tool( - "binance_us_get_oco", + server.registerTool( + "binance_us_get_oco", + { + description: "Query a specific OCO order on Binance.US. Either orderListId or origClientOrderId must be provided.", - { - orderListId: z.number().optional().describe("The order list ID to query"), - origClientOrderId: z.string().optional().describe("The original client order ID to query"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - if (!params.orderListId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "❌ Either orderListId or origClientOrderId must be provided." }], - isError: true - }; - } - - const response = await makeSignedRequest("GET", "/api/v3/orderList", params); - - const orders = response.orders || []; - - return { - content: [{ - type: "text", - text: `📋 OCO Order Details\n\n` + - `Order List ID: ${response.orderListId}\n` + - `Symbol: ${response.symbol}\n` + - `Contingency Type: ${response.contingencyType}\n` + - `List Status: ${response.listStatusType}\n` + - `List Order Status: ${response.listOrderStatus}\n` + - `Client Order ID: ${response.listClientOrderId}\n` + - `Transaction Time: ${new Date(response.transactionTime).toISOString()}\n` + - `\n--- Orders ---\n` + - orders.map((order: any) => - `• Symbol: ${order.symbol} | Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}` - ).join('\n') + - `\n\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get OCO order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + orderListId: z.number().optional().describe("The order list ID to query"), + origClientOrderId: z.string().optional().describe("The original client order ID to query"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + if (!params.orderListId && !params.origClientOrderId) { + return { + content: [ + { + type: "text", + text: "❌ Either orderListId or origClientOrderId must be provided.", + }, + ], + isError: true, + }; } - ); + + const response = await makeSignedRequest("GET", "/api/v3/orderList", params); + + const orders = response.orders || []; + + return { + content: [ + { + type: "text", + text: + `📋 OCO Order Details\n\n` + + `Order List ID: ${response.orderListId}\n` + + `Symbol: ${response.symbol}\n` + + `Contingency Type: ${response.contingencyType}\n` + + `List Status: ${response.listStatusType}\n` + + `List Order Status: ${response.listOrderStatus}\n` + + `Client Order ID: ${response.listClientOrderId}\n` + + `Transaction Time: ${new Date(response.transactionTime).toISOString()}\n` + + `\n--- Orders ---\n` + + orders + .map( + (order: any) => + `• Symbol: ${order.symbol} | Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}`, + ) + .join("\n") + + `\n\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { type: "text", text: `❌ Failed to get OCO order: ${errorMessage}${additionalHelp}` }, + ], + isError: true, + }; + } + }, + ); } /** * Register cancel OCO order tool */ export function registerBinanceUsCancelOco(server: McpServer) { - server.tool( - "binance_us_cancel_oco", + server.registerTool( + "binance_us_cancel_oco", + { + description: "Cancel an entire OCO order on Binance.US. Cancelling any individual leg will cancel the entire OCO.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), - orderListId: z.number().optional().describe("The order list ID to cancel"), - listClientOrderId: z.string().optional().describe("The list client order ID to cancel"), - newClientOrderId: z.string().optional().describe("New client order ID for this cancel request"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - if (!params.orderListId && !params.listClientOrderId) { - return { - content: [{ type: "text", text: "❌ Either orderListId or listClientOrderId must be provided." }], - isError: true - }; - } - - const response = await makeSignedRequest("DELETE", "/api/v3/orderList", params); - - const orderReports = response.orderReports || []; - - return { - content: [{ - type: "text", - text: `✅ OCO Order cancelled successfully!\n\n` + - `Order List ID: ${response.orderListId}\n` + - `Symbol: ${response.symbol}\n` + - `Status: ${response.listStatusType}\n` + - `Order Status: ${response.listOrderStatus}\n` + - `\n--- Cancelled Orders ---\n` + - orderReports.map((report: any) => - `• Order ID: ${report.orderId} | ${report.type} | ` + - `Qty: ${report.origQty} @ ${report.price} | ` + - `Status: ${report.status}` - ).join('\n') + - `\n\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to cancel OCO order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), + orderListId: z.number().optional().describe("The order list ID to cancel"), + listClientOrderId: z.string().optional().describe("The list client order ID to cancel"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for this cancel request"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + if (!params.orderListId && !params.listClientOrderId) { + return { + content: [ + { + type: "text", + text: "❌ Either orderListId or listClientOrderId must be provided.", + }, + ], + isError: true, + }; } - ); + + const response = await makeSignedRequest("DELETE", "/api/v3/orderList", params); + + const orderReports = response.orderReports || []; + + return { + content: [ + { + type: "text", + text: + `✅ OCO Order cancelled successfully!\n\n` + + `Order List ID: ${response.orderListId}\n` + + `Symbol: ${response.symbol}\n` + + `Status: ${response.listStatusType}\n` + + `Order Status: ${response.listOrderStatus}\n` + + `\n--- Cancelled Orders ---\n` + + orderReports + .map( + (report: any) => + `• Order ID: ${report.orderId} | ${report.type} | ` + + `Qty: ${report.origQty} @ ${report.price} | ` + + `Status: ${report.status}`, + ) + .join("\n") + + `\n\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel OCO order: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register open OCO orders tool */ export function registerBinanceUsOpenOco(server: McpServer) { - server.tool( - "binance_us_open_oco", - "Get all open OCO orders on Binance.US.", - { - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - const response = await makeSignedRequest("GET", "/api/v3/openOrderList", params); - - if (!response || response.length === 0) { - return { - content: [{ - type: "text", - text: `📋 No open OCO orders found` - }] - }; - } - - const ocoList = response.map((oco: any) => { - const orders = oco.orders || []; - return `\n📦 Order List ID: ${oco.orderListId}\n` + - ` Symbol: ${oco.symbol}\n` + - ` Status: ${oco.listStatusType} / ${oco.listOrderStatus}\n` + - ` Client ID: ${oco.listClientOrderId}\n` + - ` Orders:\n` + - orders.map((order: any) => - ` • Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}` - ).join('\n'); - }).join('\n'); - - return { - content: [{ - type: "text", - text: `📋 Open OCO Orders\n` + - `Total: ${response.length}\n` + - `${ocoList}\n\n` + - `Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get open OCO orders: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + server.registerTool( + "binance_us_open_oco", + { + description: "Get all open OCO orders on Binance.US.", + inputSchema: { + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + const response = await makeSignedRequest("GET", "/api/v3/openOrderList", params); + + if (!response || response.length === 0) { + return { + content: [ + { + type: "text", + text: `📋 No open OCO orders found`, + }, + ], + }; } - ); + + const ocoList = response + .map((oco: any) => { + const orders = oco.orders || []; + + return ( + `\n📦 Order List ID: ${oco.orderListId}\n` + + ` Symbol: ${oco.symbol}\n` + + ` Status: ${oco.listStatusType} / ${oco.listOrderStatus}\n` + + ` Client ID: ${oco.listClientOrderId}\n` + + ` Orders:\n` + + orders + .map( + (order: any) => + ` • Order ID: ${order.orderId} | Client ID: ${order.clientOrderId}`, + ) + .join("\n") + ); + }) + .join("\n"); + + return { + content: [ + { + type: "text", + text: + `📋 Open OCO Orders\n` + + `Total: ${response.length}\n` + + `${ocoList}\n\n` + + `Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to get open OCO orders: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register all OCO orders history tool */ export function registerBinanceUsAllOcoOrders(server: McpServer) { - server.tool( - "binance_us_all_oco_orders", - "Get all OCO orders (history) on Binance.US. Returns up to 1000 orders.", - { - fromId: z.number().optional().describe("Order list ID to start from. Cannot be used with startTime/endTime."), - startTime: z.number().optional().describe("Start time in milliseconds. Cannot be used with fromId."), - endTime: z.number().optional().describe("End time in milliseconds. Cannot be used with fromId."), - limit: z.number().optional().describe("Number of results (default 500, max 1000)"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - // Validate mutually exclusive parameters - if (params.fromId && (params.startTime || params.endTime)) { - return { - content: [{ type: "text", text: "❌ fromId cannot be used together with startTime or endTime." }], - isError: true - }; - } - - // Validate limit - if (params.limit !== undefined && (params.limit < 1 || params.limit > 1000)) { - return { - content: [{ type: "text", text: "❌ limit must be between 1 and 1000." }], - isError: true - }; - } - - const response = await makeSignedRequest("GET", "/api/v3/allOrderList", params); - - if (!response || response.length === 0) { - return { - content: [{ - type: "text", - text: `📋 No OCO order history found` - }] - }; - } - - const ocoList = response.slice(0, 10).map((oco: any) => { - const orders = oco.orders || []; - return `• List ID: ${oco.orderListId} | ${oco.symbol} | ` + - `Status: ${oco.listOrderStatus} | ` + - `Orders: ${orders.length} | ` + - `${new Date(oco.transactionTime).toISOString()}`; - }).join('\n'); - - return { - content: [{ - type: "text", - text: `📋 OCO Order History\n` + - `Total Retrieved: ${response.length}\n\n` + - `Recent Orders (showing up to 10):\n${ocoList}\n\n` + - `Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get OCO order history: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + server.registerTool( + "binance_us_all_oco_orders", + { + description: "Get all OCO orders (history) on Binance.US. Returns up to 1000 orders.", + inputSchema: { + fromId: z + .number() + .optional() + .describe("Order list ID to start from. Cannot be used with startTime/endTime."), + startTime: z + .number() + .optional() + .describe("Start time in milliseconds. Cannot be used with fromId."), + endTime: z + .number() + .optional() + .describe("End time in milliseconds. Cannot be used with fromId."), + limit: z.number().optional().describe("Number of results (default 500, max 1000)"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + // Validate mutually exclusive parameters + if (params.fromId && (params.startTime || params.endTime)) { + return { + content: [ + { + type: "text", + text: "❌ fromId cannot be used together with startTime or endTime.", + }, + ], + isError: true, + }; } - ); + + // Validate limit + if (params.limit !== undefined && (params.limit < 1 || params.limit > 1000)) { + return { + content: [{ type: "text", text: "❌ limit must be between 1 and 1000." }], + isError: true, + }; + } + + const response = await makeSignedRequest("GET", "/api/v3/allOrderList", params); + + if (!response || response.length === 0) { + return { + content: [ + { + type: "text", + text: `📋 No OCO order history found`, + }, + ], + }; + } + + const ocoList = response + .slice(0, 10) + .map((oco: any) => { + const orders = oco.orders || []; + + return ( + `• List ID: ${oco.orderListId} | ${oco.symbol} | ` + + `Status: ${oco.listOrderStatus} | ` + + `Orders: ${orders.length} | ` + + `${new Date(oco.transactionTime).toISOString()}` + ); + }) + .join("\n"); + + return { + content: [ + { + type: "text", + text: + `📋 OCO Order History\n` + + `Total Retrieved: ${response.length}\n\n` + + `Recent Orders (showing up to 10):\n${ocoList}\n\n` + + `Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to get OCO order history: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Validate OCO order parameters */ function validateOcoParams(params: any): string | null { - const { side, price, stopPrice, stopLimitPrice, stopLimitTimeInForce, quantity } = params; - - // Validate quantity - if (!quantity || quantity <= 0) { - return "❌ quantity must be greater than 0."; - } - - // Validate price - if (!price || price <= 0) { - return "❌ price must be greater than 0."; - } - - // Validate stopPrice - if (!stopPrice || stopPrice <= 0) { - return "❌ stopPrice must be greater than 0."; - } - - // Validate stop limit price requires time in force - if (stopLimitPrice && !stopLimitTimeInForce) { - return "❌ stopLimitTimeInForce is required when stopLimitPrice is provided."; - } - - // Validate price restrictions based on side with helpful warnings - if (side === "SELL" && price <= stopPrice) { - return "⚠️ For SELL OCO orders, limit price should typically be greater than stop price. " + - "Price restrictions: Limit Price > Last Price > Stop Price"; - } - - if (side === "BUY" && price >= stopPrice) { - return "⚠️ For BUY OCO orders, limit price should typically be less than stop price. " + - "Price restrictions: Limit Price < Last Price < Stop Price"; - } - - return null; + const { side, price, stopPrice, stopLimitPrice, stopLimitTimeInForce, quantity } = params; + + // Validate quantity + if (!quantity || quantity <= 0) { + return "❌ quantity must be greater than 0."; + } + + // Validate price + if (!price || price <= 0) { + return "❌ price must be greater than 0."; + } + + // Validate stopPrice + if (!stopPrice || stopPrice <= 0) { + return "❌ stopPrice must be greater than 0."; + } + + // Validate stop limit price requires time in force + if (stopLimitPrice && !stopLimitTimeInForce) { + return "❌ stopLimitTimeInForce is required when stopLimitPrice is provided."; + } + + // Validate price restrictions based on side with helpful warnings + if (side === "SELL" && price <= stopPrice) { + return ( + "⚠️ For SELL OCO orders, limit price should typically be greater than stop price. " + + "Price restrictions: Limit Price > Last Price > Stop Price" + ); + } + + if (side === "BUY" && price >= stopPrice) { + return ( + "⚠️ For BUY OCO orders, limit price should typically be less than stop price. " + + "Price restrictions: Limit Price < Last Price < Stop Price" + ); + } + + return null; } /** * Register all OCO order tools */ export function registerBinanceUsOcoTools(server: McpServer) { - registerBinanceUsNewOco(server); - registerBinanceUsGetOco(server); - registerBinanceUsCancelOco(server); - registerBinanceUsOpenOco(server); - registerBinanceUsAllOcoOrders(server); -} \ No newline at end of file + registerBinanceUsNewOco(server); + registerBinanceUsGetOco(server); + registerBinanceUsCancelOco(server); + registerBinanceUsOpenOco(server); + registerBinanceUsAllOcoOrders(server); +} diff --git a/src/tools/trade/orders.ts b/src/tools/trade/orders.ts index e6ffa262..e5b37717 100644 --- a/src/tools/trade/orders.ts +++ b/src/tools/trade/orders.ts @@ -1,108 +1,117 @@ // src/tools/trade/orders.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; -import { makeSignedRequest, hasApiCredentials, BINANCE_US_CONFIG } from "../../config/binanceUsClient.js"; + +import { + BINANCE_US_CONFIG, + hasApiCredentials, + makeSignedRequest, +} from "../../config/binanceUsClient.js"; // Common Binance error codes for better error messages const BINANCE_ERROR_CODES: Record = { - [-1000]: "Unknown error occurred", - [-1001]: "Disconnected - internal error", - [-1002]: "Unauthorized - check API key permissions", - [-1003]: "Too many requests - rate limit exceeded", - [-1006]: "Unexpected response - try again", - [-1007]: "Timeout waiting for response", - [-1013]: "Invalid quantity - check LOT_SIZE filter", - [-1014]: "Unknown order composition", - [-1015]: "Too many orders - rate limit exceeded", - [-1016]: "Service shutting down", - [-1020]: "Unsupported operation", - [-1021]: "Invalid timestamp - check recvWindow", - [-1022]: "Invalid signature", - [-1100]: "Illegal characters in parameter", - [-1101]: "Too many parameters sent", - [-1102]: "Mandatory parameter missing", - [-1103]: "Unknown parameter sent", - [-1104]: "Not all parameters read", - [-1105]: "Parameter is empty", - [-1106]: "Parameter not required", - [-1111]: "Precision over maximum for asset", - [-1112]: "No orders on book for symbol", - [-1114]: "TimeInForce parameter not required", - [-1115]: "Invalid timeInForce value", - [-1116]: "Invalid orderType value", - [-1117]: "Invalid side value", - [-1118]: "New client order ID is empty", - [-1119]: "Original client order ID is empty", - [-1120]: "Invalid interval value", - [-1121]: "Invalid symbol", - [-1125]: "Invalid listen key", - [-1127]: "Listen key lookup interval too big", - [-1128]: "Invalid optional parameter combination", - [-1130]: "Invalid data sent for parameter", - [-2010]: "New order rejected", - [-2011]: "Cancel rejected - check order status", - [-2013]: "Order does not exist", - [-2014]: "API key format invalid", - [-2015]: "Rejected - invalid API key, IP, or permissions", - [-2016]: "No trading window could be found", - [-2018]: "Balance is insufficient", - [-2019]: "Margin is insufficient", - [-2020]: "Unable to fill order", - [-2021]: "Order would immediately trigger stop price", - [-2022]: "ReduceOnly rejected - position already reduced", - [-2024]: "Position does not exist", - [-2026]: "Order would immediately match and trade" + [-1000]: "Unknown error occurred", + [-1001]: "Disconnected - internal error", + [-1002]: "Unauthorized - check API key permissions", + [-1003]: "Too many requests - rate limit exceeded", + [-1006]: "Unexpected response - try again", + [-1007]: "Timeout waiting for response", + [-1013]: "Invalid quantity - check LOT_SIZE filter", + [-1014]: "Unknown order composition", + [-1015]: "Too many orders - rate limit exceeded", + [-1016]: "Service shutting down", + [-1020]: "Unsupported operation", + [-1021]: "Invalid timestamp - check recvWindow", + [-1022]: "Invalid signature", + [-1100]: "Illegal characters in parameter", + [-1101]: "Too many parameters sent", + [-1102]: "Mandatory parameter missing", + [-1103]: "Unknown parameter sent", + [-1104]: "Not all parameters read", + [-1105]: "Parameter is empty", + [-1106]: "Parameter not required", + [-1111]: "Precision over maximum for asset", + [-1112]: "No orders on book for symbol", + [-1114]: "TimeInForce parameter not required", + [-1115]: "Invalid timeInForce value", + [-1116]: "Invalid orderType value", + [-1117]: "Invalid side value", + [-1118]: "New client order ID is empty", + [-1119]: "Original client order ID is empty", + [-1120]: "Invalid interval value", + [-1121]: "Invalid symbol", + [-1125]: "Invalid listen key", + [-1127]: "Listen key lookup interval too big", + [-1128]: "Invalid optional parameter combination", + [-1130]: "Invalid data sent for parameter", + [-2010]: "New order rejected", + [-2011]: "Cancel rejected - check order status", + [-2013]: "Order does not exist", + [-2014]: "API key format invalid", + [-2015]: "Rejected - invalid API key, IP, or permissions", + [-2016]: "No trading window could be found", + [-2018]: "Balance is insufficient", + [-2019]: "Margin is insufficient", + [-2020]: "Unable to fill order", + [-2021]: "Order would immediately trigger stop price", + [-2022]: "ReduceOnly rejected - position already reduced", + [-2024]: "Position does not exist", + [-2026]: "Order would immediately match and trade", }; /** * Get human-readable error message for Binance error code */ function getBinanceErrorMessage(code: number): string { - return BINANCE_ERROR_CODES[code] || `Unknown error code: ${code}`; + return BINANCE_ERROR_CODES[code] || `Unknown error code: ${code}`; } /** * Check API credentials before making requests */ function checkCredentials(): string | null { - if (!hasApiCredentials()) { - return "❌ API credentials not configured. Please set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables."; - } - return null; + if (!hasApiCredentials()) { + return "❌ API credentials not configured. Please set BINANCE_US_API_KEY and BINANCE_US_API_SECRET environment variables."; + } + + return null; } /** * Validate recvWindow parameter */ function validateRecvWindow(recvWindow?: number): string | null { - if (recvWindow !== undefined && recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { - return `❌ recvWindow cannot exceed ${BINANCE_US_CONFIG.MAX_RECV_WINDOW}ms (60 seconds).`; - } - return null; + if (recvWindow !== undefined && recvWindow > BINANCE_US_CONFIG.MAX_RECV_WINDOW) { + return `❌ recvWindow cannot exceed ${BINANCE_US_CONFIG.MAX_RECV_WINDOW}ms (60 seconds).`; + } + + return null; } /** * Validate symbol format (basic check) */ function validateSymbol(symbol: string): string | null { - if (!symbol || symbol.length < 2 || symbol.length > 20) { - return "❌ Invalid symbol format. Symbol should be 2-20 characters (e.g., BTCUSD, ETHUSD)."; - } - if (!/^[A-Z0-9]+$/.test(symbol.toUpperCase())) { - return "❌ Invalid symbol format. Symbol should contain only letters and numbers."; - } - return null; + if (!symbol || symbol.length < 2 || symbol.length > 20) { + return "❌ Invalid symbol format. Symbol should be 2-20 characters (e.g., BTCUSD, ETHUSD)."; + } + if (!/^[A-Z0-9]+$/.test(symbol.toUpperCase())) { + return "❌ Invalid symbol format. Symbol should contain only letters and numbers."; + } + + return null; } // Order type enum const OrderType = z.enum([ - "LIMIT", - "MARKET", - "STOP_LOSS", - "STOP_LOSS_LIMIT", - "TAKE_PROFIT", - "TAKE_PROFIT_LIMIT", - "LIMIT_MAKER" + "LIMIT", + "MARKET", + "STOP_LOSS", + "STOP_LOSS_LIMIT", + "TAKE_PROFIT", + "TAKE_PROFIT_LIMIT", + "LIMIT_MAKER", ]); // Time in force enum @@ -127,628 +136,851 @@ const CancelRestrictions = z.enum(["ONLY_NEW", "ONLY_PARTIALLY_FILLED"]); * Register new order tool */ export function registerBinanceUsNewOrder(server: McpServer) { - server.tool( - "binance_us_new_order", + server.registerTool( + "binance_us_new_order", + { + description: "Place a new trade order on Binance.US. Supports LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, and LIMIT_MAKER order types.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), - side: OrderSide.describe("Order side: BUY or SELL"), - type: OrderType.describe("Order type: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER"), - timeInForce: TimeInForce.optional().describe("Time in force: GTC (Good Till Cancel), IOC (Immediate Or Cancel), FOK (Fill Or Kill). Required for LIMIT orders."), - quantity: z.number().optional().describe("Order quantity in base asset. Required for most order types."), - quoteOrderQty: z.number().optional().describe("Order quantity in quote asset. Can be used for MARKET orders instead of quantity."), - price: z.number().optional().describe("Order price. Required for LIMIT and LIMIT_MAKER orders."), - newClientOrderId: z.string().optional().describe("Unique client order ID. Auto-generated if not provided."), - stopPrice: z.number().optional().describe("Stop price. Required for STOP_LOSS_LIMIT and TAKE_PROFIT_LIMIT orders."), - trailingDelta: z.number().optional().describe("Trailing delta for trailing stop orders in BIPS (1 BIP = 0.01%)."), - icebergQty: z.number().optional().describe("Iceberg quantity for iceberg orders. timeInForce must be GTC."), - newOrderRespType: OrderRespType.optional().describe("Response type: ACK, RESULT, or FULL. MARKET/LIMIT default to FULL, others to ACK."), - selfTradePreventionMode: SelfTradePreventionMode.optional().describe("Self-trade prevention mode: EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH, NONE."), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000).") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - - // Validate recvWindow - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - // Validate order type requirements - const validationError = validateOrderParams(params); - if (validationError) { - return { - content: [{ type: "text", text: validationError }], - isError: true - }; - } - - const response = await makeSignedRequest("POST", "/api/v3/order", params); - - return { - content: [{ - type: "text", - text: `✅ Order placed successfully!\n\n` + - `Order ID: ${response.orderId}\n` + - `Symbol: ${response.symbol}\n` + - `Side: ${response.side}\n` + - `Type: ${response.type}\n` + - `Status: ${response.status || 'PENDING'}\n` + - (response.price ? `Price: ${response.price}\n` : '') + - (response.origQty ? `Quantity: ${response.origQty}\n` : '') + - (response.executedQty ? `Executed: ${response.executedQty}\n` : '') + - `\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - // Try to extract Binance error code for better messaging - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to place order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), + side: OrderSide.describe("Order side: BUY or SELL"), + type: OrderType.describe( + "Order type: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER", + ), + timeInForce: TimeInForce.optional().describe( + "Time in force: GTC (Good Till Cancel), IOC (Immediate Or Cancel), FOK (Fill Or Kill). Required for LIMIT orders.", + ), + quantity: z + .number() + .optional() + .describe("Order quantity in base asset. Required for most order types."), + quoteOrderQty: z + .number() + .optional() + .describe( + "Order quantity in quote asset. Can be used for MARKET orders instead of quantity.", + ), + price: z + .number() + .optional() + .describe("Order price. Required for LIMIT and LIMIT_MAKER orders."), + newClientOrderId: z + .string() + .optional() + .describe("Unique client order ID. Auto-generated if not provided."), + stopPrice: z + .number() + .optional() + .describe("Stop price. Required for STOP_LOSS_LIMIT and TAKE_PROFIT_LIMIT orders."), + trailingDelta: z + .number() + .optional() + .describe("Trailing delta for trailing stop orders in BIPS (1 BIP = 0.01%)."), + icebergQty: z + .number() + .optional() + .describe("Iceberg quantity for iceberg orders. timeInForce must be GTC."), + newOrderRespType: OrderRespType.optional().describe( + "Response type: ACK, RESULT, or FULL. MARKET/LIMIT default to FULL, others to ACK.", + ), + selfTradePreventionMode: SelfTradePreventionMode.optional().describe( + "Self-trade prevention mode: EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH, NONE.", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)."), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + + // Validate recvWindow + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + // Validate order type requirements + const validationError = validateOrderParams(params); + if (validationError) { + return { + content: [{ type: "text", text: validationError }], + isError: true, + }; } - ); + + const response = await makeSignedRequest("POST", "/api/v3/order", params); + + return { + content: [ + { + type: "text", + text: + `✅ Order placed successfully!\n\n` + + `Order ID: ${response.orderId}\n` + + `Symbol: ${response.symbol}\n` + + `Side: ${response.side}\n` + + `Type: ${response.type}\n` + + `Status: ${response.status || "PENDING"}\n` + + (response.price ? `Price: ${response.price}\n` : "") + + (response.origQty ? `Quantity: ${response.origQty}\n` : "") + + (response.executedQty ? `Executed: ${response.executedQty}\n` : "") + + `\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + // Try to extract Binance error code for better messaging + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { type: "text", text: `❌ Failed to place order: ${errorMessage}${additionalHelp}` }, + ], + isError: true, + }; + } + }, + ); } /** * Register test order tool */ export function registerBinanceUsTestOrder(server: McpServer) { - server.tool( - "binance_us_test_order", + server.registerTool( + "binance_us_test_order", + { + description: "Test a new order on Binance.US without actually placing it. Validates order parameters and signature without executing the trade.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), - side: OrderSide.describe("Order side: BUY or SELL"), - type: OrderType.describe("Order type: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER"), - timeInForce: TimeInForce.optional().describe("Time in force: GTC, IOC, or FOK"), - quantity: z.number().optional().describe("Order quantity in base asset"), - quoteOrderQty: z.number().optional().describe("Order quantity in quote asset (for MARKET orders)"), - price: z.number().optional().describe("Order price"), - newClientOrderId: z.string().optional().describe("Unique client order ID"), - stopPrice: z.number().optional().describe("Stop price for stop orders"), - trailingDelta: z.number().optional().describe("Trailing delta in BIPS"), - icebergQty: z.number().optional().describe("Iceberg quantity"), - newOrderRespType: OrderRespType.optional().describe("Response type"), - selfTradePreventionMode: SelfTradePreventionMode.optional().describe("Self-trade prevention mode"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - const validationError = validateOrderParams(params); - if (validationError) { - return { - content: [{ type: "text", text: validationError }], - isError: true - }; - } - - await makeSignedRequest("POST", "/api/v3/order/test", params); - - return { - content: [{ - type: "text", - text: `✅ Test order validated successfully!\n\n` + - `Symbol: ${params.symbol}\n` + - `Side: ${params.side}\n` + - `Type: ${params.type}\n` + - (params.quantity ? `Quantity: ${params.quantity}\n` : '') + - (params.price ? `Price: ${params.price}\n` : '') + - `\nThe order parameters are valid and can be submitted.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Test order validation failed: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD, ETHUSD)"), + side: OrderSide.describe("Order side: BUY or SELL"), + type: OrderType.describe( + "Order type: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER", + ), + timeInForce: TimeInForce.optional().describe("Time in force: GTC, IOC, or FOK"), + quantity: z.number().optional().describe("Order quantity in base asset"), + quoteOrderQty: z + .number() + .optional() + .describe("Order quantity in quote asset (for MARKET orders)"), + price: z.number().optional().describe("Order price"), + newClientOrderId: z.string().optional().describe("Unique client order ID"), + stopPrice: z.number().optional().describe("Stop price for stop orders"), + trailingDelta: z.number().optional().describe("Trailing delta in BIPS"), + icebergQty: z.number().optional().describe("Iceberg quantity"), + newOrderRespType: OrderRespType.optional().describe("Response type"), + selfTradePreventionMode: SelfTradePreventionMode.optional().describe( + "Self-trade prevention mode", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + const validationError = validateOrderParams(params); + if (validationError) { + return { + content: [{ type: "text", text: validationError }], + isError: true, + }; } - ); + + await makeSignedRequest("POST", "/api/v3/order/test", params); + + return { + content: [ + { + type: "text", + text: + `✅ Test order validated successfully!\n\n` + + `Symbol: ${params.symbol}\n` + + `Side: ${params.side}\n` + + `Type: ${params.type}\n` + + (params.quantity ? `Quantity: ${params.quantity}\n` : "") + + (params.price ? `Price: ${params.price}\n` : "") + + `\nThe order parameters are valid and can be submitted.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Test order validation failed: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register get order tool */ export function registerBinanceUsGetOrder(server: McpServer) { - server.tool( - "binance_us_get_order", + server.registerTool( + "binance_us_get_order", + { + description: "Query the status of a specific order on Binance.US. Either orderId or origClientOrderId must be provided.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), - orderId: z.number().optional().describe("The order ID to query"), - origClientOrderId: z.string().optional().describe("The original client order ID to query"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "❌ Either orderId or origClientOrderId must be provided." }], - isError: true - }; - } - - const response = await makeSignedRequest("GET", "/api/v3/order", params); - - return { - content: [{ - type: "text", - text: `📋 Order Status\n\n` + - `Order ID: ${response.orderId}\n` + - `Symbol: ${response.symbol}\n` + - `Status: ${response.status}\n` + - `Side: ${response.side}\n` + - `Type: ${response.type}\n` + - `Price: ${response.price}\n` + - `Original Qty: ${response.origQty}\n` + - `Executed Qty: ${response.executedQty}\n` + - `Time In Force: ${response.timeInForce}\n` + - (response.stopPrice !== "0.00000000" ? `Stop Price: ${response.stopPrice}\n` : '') + - `Created: ${new Date(response.time).toISOString()}\n` + - `Updated: ${new Date(response.updateTime).toISOString()}\n` + - `\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), + orderId: z.number().optional().describe("The order ID to query"), + origClientOrderId: z.string().optional().describe("The original client order ID to query"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "❌ Either orderId or origClientOrderId must be provided." }, + ], + isError: true, + }; } - ); + + const response = await makeSignedRequest("GET", "/api/v3/order", params); + + return { + content: [ + { + type: "text", + text: + `📋 Order Status\n\n` + + `Order ID: ${response.orderId}\n` + + `Symbol: ${response.symbol}\n` + + `Status: ${response.status}\n` + + `Side: ${response.side}\n` + + `Type: ${response.type}\n` + + `Price: ${response.price}\n` + + `Original Qty: ${response.origQty}\n` + + `Executed Qty: ${response.executedQty}\n` + + `Time In Force: ${response.timeInForce}\n` + + (response.stopPrice !== "0.00000000" ? `Stop Price: ${response.stopPrice}\n` : "") + + `Created: ${new Date(response.time).toISOString()}\n` + + `Updated: ${new Date(response.updateTime).toISOString()}\n` + + `\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { type: "text", text: `❌ Failed to get order: ${errorMessage}${additionalHelp}` }, + ], + isError: true, + }; + } + }, + ); } /** * Register cancel order tool */ export function registerBinanceUsCancelOrder(server: McpServer) { - server.tool( - "binance_us_cancel_order", + server.registerTool( + "binance_us_cancel_order", + { + description: "Cancel an active order on Binance.US. Either orderId or origClientOrderId must be provided.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), - orderId: z.number().optional().describe("The order ID to cancel"), - origClientOrderId: z.string().optional().describe("The original client order ID to cancel"), - newClientOrderId: z.string().optional().describe("New client order ID for this cancel request"), - cancelRestrictions: CancelRestrictions.optional().describe("Cancel restrictions: ONLY_NEW or ONLY_PARTIALLY_FILLED"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - if (!params.orderId && !params.origClientOrderId) { - return { - content: [{ type: "text", text: "❌ Either orderId or origClientOrderId must be provided." }], - isError: true - }; - } - - const response = await makeSignedRequest("DELETE", "/api/v3/order", params); - - return { - content: [{ - type: "text", - text: `✅ Order cancelled successfully!\n\n` + - `Order ID: ${response.orderId}\n` + - `Symbol: ${response.symbol}\n` + - `Status: ${response.status}\n` + - `Side: ${response.side}\n` + - `Type: ${response.type}\n` + - `Price: ${response.price}\n` + - `Original Qty: ${response.origQty}\n` + - `Executed Qty: ${response.executedQty}\n` + - `\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to cancel order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), + orderId: z.number().optional().describe("The order ID to cancel"), + origClientOrderId: z.string().optional().describe("The original client order ID to cancel"), + newClientOrderId: z + .string() + .optional() + .describe("New client order ID for this cancel request"), + cancelRestrictions: CancelRestrictions.optional().describe( + "Cancel restrictions: ONLY_NEW or ONLY_PARTIALLY_FILLED", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + if (!params.orderId && !params.origClientOrderId) { + return { + content: [ + { type: "text", text: "❌ Either orderId or origClientOrderId must be provided." }, + ], + isError: true, + }; } - ); + + const response = await makeSignedRequest("DELETE", "/api/v3/order", params); + + return { + content: [ + { + type: "text", + text: + `✅ Order cancelled successfully!\n\n` + + `Order ID: ${response.orderId}\n` + + `Symbol: ${response.symbol}\n` + + `Status: ${response.status}\n` + + `Side: ${response.side}\n` + + `Type: ${response.type}\n` + + `Price: ${response.price}\n` + + `Original Qty: ${response.origQty}\n` + + `Executed Qty: ${response.executedQty}\n` + + `\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { type: "text", text: `❌ Failed to cancel order: ${errorMessage}${additionalHelp}` }, + ], + isError: true, + }; + } + }, + ); } /** * Register cancel and replace order tool */ export function registerBinanceUsCancelReplace(server: McpServer) { - server.tool( - "binance_us_cancel_replace", + server.registerTool( + "binance_us_cancel_replace", + { + description: "Cancel an existing order and place a new order on the same symbol atomically. This is useful for modifying order parameters.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), - side: OrderSide.describe("Order side: BUY or SELL"), - type: OrderType.describe("Order type for the new order"), - cancelReplaceMode: CancelReplaceMode.describe("STOP_ON_FAILURE: Don't place new order if cancel fails. ALLOW_FAILURE: Place new order even if cancel fails."), - cancelOrderId: z.number().optional().describe("Order ID to cancel. Either this or cancelOrigClientOrderId required."), - cancelOrigClientOrderId: z.string().optional().describe("Client order ID to cancel. Either this or cancelOrderId required."), - timeInForce: TimeInForce.optional().describe("Time in force for new order"), - quantity: z.number().optional().describe("Quantity for new order"), - quoteOrderQty: z.number().optional().describe("Quote order quantity for new order"), - price: z.number().optional().describe("Price for new order"), - cancelNewClientOrderId: z.string().optional().describe("Client order ID for the cancel"), - newClientOrderId: z.string().optional().describe("Client order ID for the new order"), - stopPrice: z.number().optional().describe("Stop price for new order"), - trailingDelta: z.number().optional().describe("Trailing delta for new order"), - icebergQty: z.number().optional().describe("Iceberg quantity for new order"), - newOrderRespType: OrderRespType.optional().describe("Response type for new order"), - selfTradePreventionMode: SelfTradePreventionMode.optional().describe("Self-trade prevention mode"), - cancelRestrictions: CancelRestrictions.optional().describe("Cancel restrictions"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - if (!params.cancelOrderId && !params.cancelOrigClientOrderId) { - return { - content: [{ type: "text", text: "❌ Either cancelOrderId or cancelOrigClientOrderId must be provided." }], - isError: true - }; - } - - const response = await makeSignedRequest("POST", "/api/v3/order/cancelReplace", params); - - return { - content: [{ - type: "text", - text: `✅ Cancel and Replace completed!\n\n` + - `Cancel Result: ${response.cancelResult}\n` + - `New Order Result: ${response.newOrderResult}\n` + - `\n--- Cancelled Order ---\n` + - (response.cancelResponse ? - `Order ID: ${response.cancelResponse.orderId}\n` + - `Status: ${response.cancelResponse.status}\n` : - 'N/A\n') + - `\n--- New Order ---\n` + - (response.newOrderResponse ? - `Order ID: ${response.newOrderResponse.orderId}\n` + - `Status: ${response.newOrderResponse.status}\n` + - `Price: ${response.newOrderResponse.price}\n` + - `Quantity: ${response.newOrderResponse.origQty}\n` : - 'N/A\n') + - `\nFull Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to cancel and replace order: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), + side: OrderSide.describe("Order side: BUY or SELL"), + type: OrderType.describe("Order type for the new order"), + cancelReplaceMode: CancelReplaceMode.describe( + "STOP_ON_FAILURE: Don't place new order if cancel fails. ALLOW_FAILURE: Place new order even if cancel fails.", + ), + cancelOrderId: z + .number() + .optional() + .describe("Order ID to cancel. Either this or cancelOrigClientOrderId required."), + cancelOrigClientOrderId: z + .string() + .optional() + .describe("Client order ID to cancel. Either this or cancelOrderId required."), + timeInForce: TimeInForce.optional().describe("Time in force for new order"), + quantity: z.number().optional().describe("Quantity for new order"), + quoteOrderQty: z.number().optional().describe("Quote order quantity for new order"), + price: z.number().optional().describe("Price for new order"), + cancelNewClientOrderId: z.string().optional().describe("Client order ID for the cancel"), + newClientOrderId: z.string().optional().describe("Client order ID for the new order"), + stopPrice: z.number().optional().describe("Stop price for new order"), + trailingDelta: z.number().optional().describe("Trailing delta for new order"), + icebergQty: z.number().optional().describe("Iceberg quantity for new order"), + newOrderRespType: OrderRespType.optional().describe("Response type for new order"), + selfTradePreventionMode: SelfTradePreventionMode.optional().describe( + "Self-trade prevention mode", + ), + cancelRestrictions: CancelRestrictions.optional().describe("Cancel restrictions"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + if (!params.cancelOrderId && !params.cancelOrigClientOrderId) { + return { + content: [ + { + type: "text", + text: "❌ Either cancelOrderId or cancelOrigClientOrderId must be provided.", + }, + ], + isError: true, + }; } - ); + + const response = await makeSignedRequest("POST", "/api/v3/order/cancelReplace", params); + + return { + content: [ + { + type: "text", + text: + `✅ Cancel and Replace completed!\n\n` + + `Cancel Result: ${response.cancelResult}\n` + + `New Order Result: ${response.newOrderResult}\n` + + `\n--- Cancelled Order ---\n` + + (response.cancelResponse + ? `Order ID: ${response.cancelResponse.orderId}\n` + + `Status: ${response.cancelResponse.status}\n` + : "N/A\n") + + `\n--- New Order ---\n` + + (response.newOrderResponse + ? `Order ID: ${response.newOrderResponse.orderId}\n` + + `Status: ${response.newOrderResponse.status}\n` + + `Price: ${response.newOrderResponse.price}\n` + + `Quantity: ${response.newOrderResponse.origQty}\n` + : "N/A\n") + + `\nFull Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel and replace order: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register open orders tool */ export function registerBinanceUsOpenOrders(server: McpServer) { - server.tool( - "binance_us_open_orders", + server.registerTool( + "binance_us_open_orders", + { + description: "Get all open orders on Binance.US. Can be filtered by symbol. Warning: Querying without symbol is heavier on rate limits (weight 40 vs 3).", - { - symbol: z.string().optional().describe("Trading pair symbol to filter by (e.g., BTCUSD). If omitted, returns all open orders."), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate optional symbol and recvWindow - if (params.symbol) { - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - } - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - const response = await makeSignedRequest("GET", "/api/v3/openOrders", params); - - if (!response || response.length === 0) { - return { - content: [{ - type: "text", - text: params.symbol - ? `📋 No open orders found for ${params.symbol}` - : `📋 No open orders found` - }] - }; - } - - const orderList = response.map((order: any) => - `• ${order.symbol} | ${order.side} ${order.type} | ` + - `Qty: ${order.origQty} @ ${order.price} | ` + - `Status: ${order.status} | ID: ${order.orderId}` - ).join('\n'); - - return { - content: [{ - type: "text", - text: `📋 Open Orders${params.symbol ? ` for ${params.symbol}` : ''}\n` + - `Total: ${response.length}\n\n` + - `${orderList}\n\n` + - `Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get open orders: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .optional() + .describe( + "Trading pair symbol to filter by (e.g., BTCUSD). If omitted, returns all open orders.", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate optional symbol and recvWindow + if (params.symbol) { + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + } + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + const response = await makeSignedRequest("GET", "/api/v3/openOrders", params); + + if (!response || response.length === 0) { + return { + content: [ + { + type: "text", + text: params.symbol + ? `📋 No open orders found for ${params.symbol}` + : `📋 No open orders found`, + }, + ], + }; } - ); + + const orderList = response + .map( + (order: any) => + `• ${order.symbol} | ${order.side} ${order.type} | ` + + `Qty: ${order.origQty} @ ${order.price} | ` + + `Status: ${order.status} | ID: ${order.orderId}`, + ) + .join("\n"); + + return { + content: [ + { + type: "text", + text: + `📋 Open Orders${params.symbol ? ` for ${params.symbol}` : ""}\n` + + `Total: ${response.length}\n\n` + + `${orderList}\n\n` + + `Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to get open orders: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register all orders history tool */ export function registerBinanceUsAllOrders(server: McpServer) { - server.tool( - "binance_us_all_orders", + server.registerTool( + "binance_us_all_orders", + { + description: "Get all orders (active, canceled, or filled) for a symbol on Binance.US. Returns order history.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), - orderId: z.number().optional().describe("Order ID to start from. Gets orders >= this orderId."), - startTime: z.number().optional().describe("Start time in milliseconds"), - endTime: z.number().optional().describe("End time in milliseconds"), - limit: z.number().optional().describe("Number of orders to return (default 500, max 1000)"), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol and recvWindow - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - // Validate limit - if (params.limit !== undefined && (params.limit < 1 || params.limit > 1000)) { - return { - content: [{ type: "text", text: "❌ limit must be between 1 and 1000." }], - isError: true - }; - } - - const response = await makeSignedRequest("GET", "/api/v3/allOrders", params); - - if (!response || response.length === 0) { - return { - content: [{ - type: "text", - text: `📋 No orders found for ${params.symbol}` - }] - }; - } - - const orderList = response.slice(0, 10).map((order: any) => - `• ${order.side} ${order.type} | Qty: ${order.origQty} @ ${order.price} | ` + - `Status: ${order.status} | ID: ${order.orderId} | ${new Date(order.time).toISOString()}` - ).join('\n'); - - return { - content: [{ - type: "text", - text: `📋 Order History for ${params.symbol}\n` + - `Total Retrieved: ${response.length}\n\n` + - `Recent Orders (showing up to 10):\n${orderList}\n\n` + - `Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to get order history: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD)"), + orderId: z + .number() + .optional() + .describe("Order ID to start from. Gets orders >= this orderId."), + startTime: z.number().optional().describe("Start time in milliseconds"), + endTime: z.number().optional().describe("End time in milliseconds"), + limit: z.number().optional().describe("Number of orders to return (default 500, max 1000)"), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol and recvWindow + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + // Validate limit + if (params.limit !== undefined && (params.limit < 1 || params.limit > 1000)) { + return { + content: [{ type: "text", text: "❌ limit must be between 1 and 1000." }], + isError: true, + }; } - ); + + const response = await makeSignedRequest("GET", "/api/v3/allOrders", params); + + if (!response || response.length === 0) { + return { + content: [ + { + type: "text", + text: `📋 No orders found for ${params.symbol}`, + }, + ], + }; + } + + const orderList = response + .slice(0, 10) + .map( + (order: any) => + `• ${order.side} ${order.type} | Qty: ${order.origQty} @ ${order.price} | ` + + `Status: ${order.status} | ID: ${order.orderId} | ${new Date(order.time).toISOString()}`, + ) + .join("\n"); + + return { + content: [ + { + type: "text", + text: + `📋 Order History for ${params.symbol}\n` + + `Total Retrieved: ${response.length}\n\n` + + `Recent Orders (showing up to 10):\n${orderList}\n\n` + + `Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to get order history: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Validate order parameters based on order type */ function validateOrderParams(params: any): string | null { - const { type, timeInForce, quantity, quoteOrderQty, price, stopPrice, trailingDelta, icebergQty } = params; - - switch (type) { - case "LIMIT": - if (!timeInForce) return "❌ LIMIT orders require timeInForce parameter."; - if (!quantity) return "❌ LIMIT orders require quantity parameter."; - if (!price) return "❌ LIMIT orders require price parameter."; - break; - - case "MARKET": - if (!quantity && !quoteOrderQty) return "❌ MARKET orders require either quantity or quoteOrderQty."; - break; - - case "STOP_LOSS": - if (!quantity) return "❌ STOP_LOSS orders require quantity parameter."; - if (!stopPrice && !trailingDelta) return "❌ STOP_LOSS orders require stopPrice or trailingDelta."; - break; - - case "STOP_LOSS_LIMIT": - if (!timeInForce) return "❌ STOP_LOSS_LIMIT orders require timeInForce parameter."; - if (!quantity) return "❌ STOP_LOSS_LIMIT orders require quantity parameter."; - if (!price) return "❌ STOP_LOSS_LIMIT orders require price parameter."; - if (!stopPrice && !trailingDelta) return "❌ STOP_LOSS_LIMIT orders require stopPrice or trailingDelta."; - break; - - case "TAKE_PROFIT": - if (!quantity) return "❌ TAKE_PROFIT orders require quantity parameter."; - if (!stopPrice && !trailingDelta) return "❌ TAKE_PROFIT orders require stopPrice or trailingDelta."; - break; - - case "TAKE_PROFIT_LIMIT": - if (!timeInForce) return "❌ TAKE_PROFIT_LIMIT orders require timeInForce parameter."; - if (!quantity) return "❌ TAKE_PROFIT_LIMIT orders require quantity parameter."; - if (!price) return "❌ TAKE_PROFIT_LIMIT orders require price parameter."; - if (!stopPrice && !trailingDelta) return "❌ TAKE_PROFIT_LIMIT orders require stopPrice or trailingDelta."; - break; - - case "LIMIT_MAKER": - if (!quantity) return "❌ LIMIT_MAKER orders require quantity parameter."; - if (!price) return "❌ LIMIT_MAKER orders require price parameter."; - break; - } - - // Iceberg order validation - if (icebergQty && timeInForce !== "GTC") { - return "❌ Iceberg orders must have timeInForce set to GTC."; - } - - return null; + const { + type, + timeInForce, + quantity, + quoteOrderQty, + price, + stopPrice, + trailingDelta, + icebergQty, + } = params; + + switch (type) { + case "LIMIT": + if (!timeInForce) return "❌ LIMIT orders require timeInForce parameter."; + if (!quantity) return "❌ LIMIT orders require quantity parameter."; + if (!price) return "❌ LIMIT orders require price parameter."; + break; + + case "MARKET": + if (!quantity && !quoteOrderQty) + return "❌ MARKET orders require either quantity or quoteOrderQty."; + break; + + case "STOP_LOSS": + if (!quantity) return "❌ STOP_LOSS orders require quantity parameter."; + if (!stopPrice && !trailingDelta) + return "❌ STOP_LOSS orders require stopPrice or trailingDelta."; + break; + + case "STOP_LOSS_LIMIT": + if (!timeInForce) return "❌ STOP_LOSS_LIMIT orders require timeInForce parameter."; + if (!quantity) return "❌ STOP_LOSS_LIMIT orders require quantity parameter."; + if (!price) return "❌ STOP_LOSS_LIMIT orders require price parameter."; + if (!stopPrice && !trailingDelta) + return "❌ STOP_LOSS_LIMIT orders require stopPrice or trailingDelta."; + break; + + case "TAKE_PROFIT": + if (!quantity) return "❌ TAKE_PROFIT orders require quantity parameter."; + if (!stopPrice && !trailingDelta) + return "❌ TAKE_PROFIT orders require stopPrice or trailingDelta."; + break; + + case "TAKE_PROFIT_LIMIT": + if (!timeInForce) return "❌ TAKE_PROFIT_LIMIT orders require timeInForce parameter."; + if (!quantity) return "❌ TAKE_PROFIT_LIMIT orders require quantity parameter."; + if (!price) return "❌ TAKE_PROFIT_LIMIT orders require price parameter."; + if (!stopPrice && !trailingDelta) + return "❌ TAKE_PROFIT_LIMIT orders require stopPrice or trailingDelta."; + break; + + case "LIMIT_MAKER": + if (!quantity) return "❌ LIMIT_MAKER orders require quantity parameter."; + if (!price) return "❌ LIMIT_MAKER orders require price parameter."; + break; + } + + // Iceberg order validation + if (icebergQty && timeInForce !== "GTC") { + return "❌ Iceberg orders must have timeInForce set to GTC."; + } + + return null; } /** * Register cancel all open orders for symbol tool */ export function registerBinanceUsCancelAllOpenOrders(server: McpServer) { - server.tool( - "binance_us_cancel_all_open_orders", + server.registerTool( + "binance_us_cancel_all_open_orders", + { + description: "Cancel all active orders on a symbol on Binance.US. This includes OCO orders. Use with caution - this will cancel ALL open orders for the specified symbol.", - { - symbol: z.string().describe("Trading pair symbol (e.g., BTCUSD). Required - all open orders for this symbol will be cancelled."), - recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)") - }, - async (params) => { - try { - // Check API credentials first - const credError = checkCredentials(); - if (credError) return { content: [{ type: "text", text: credError }], isError: true }; - - // Validate symbol - const symbolError = validateSymbol(params.symbol); - if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; - - // Validate recvWindow - const recvWindowError = validateRecvWindow(params.recvWindow); - if (recvWindowError) return { content: [{ type: "text", text: recvWindowError }], isError: true }; - - const response = await makeSignedRequest("DELETE", "/api/v3/openOrders", params); - - if (!response || response.length === 0) { - return { - content: [{ - type: "text", - text: `📋 No open orders found to cancel for ${params.symbol}` - }] - }; - } - - const cancelledList = response.map((order: any) => - `• Order ID: ${order.orderId} | ${order.side} ${order.type} | ` + - `Qty: ${order.origQty} @ ${order.price} | Status: ${order.status}` - ).join('\n'); - - return { - content: [{ - type: "text", - text: `✅ Cancelled ${response.length} orders for ${params.symbol}!\n\n` + - `Cancelled Orders:\n${cancelledList}\n\n` + - `Full Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); - const additionalHelp = codeMatch && codeMatch[1] ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` : ''; - return { - content: [{ type: "text", text: `❌ Failed to cancel all open orders: ${errorMessage}${additionalHelp}` }], - isError: true - }; - } + inputSchema: { + symbol: z + .string() + .describe( + "Trading pair symbol (e.g., BTCUSD). Required - all open orders for this symbol will be cancelled.", + ), + recvWindow: z.number().optional().describe("Receive window in milliseconds (max 60000)"), + }, + }, + async (params) => { + try { + // Check API credentials first + const credError = checkCredentials(); + if (credError) return { content: [{ type: "text", text: credError }], isError: true }; + + // Validate symbol + const symbolError = validateSymbol(params.symbol); + if (symbolError) return { content: [{ type: "text", text: symbolError }], isError: true }; + + // Validate recvWindow + const recvWindowError = validateRecvWindow(params.recvWindow); + if (recvWindowError) + return { content: [{ type: "text", text: recvWindowError }], isError: true }; + + const response = await makeSignedRequest("DELETE", "/api/v3/openOrders", params); + + if (!response || response.length === 0) { + return { + content: [ + { + type: "text", + text: `📋 No open orders found to cancel for ${params.symbol}`, + }, + ], + }; } - ); + + const cancelledList = response + .map( + (order: any) => + `• Order ID: ${order.orderId} | ${order.side} ${order.type} | ` + + `Qty: ${order.origQty} @ ${order.price} | Status: ${order.status}`, + ) + .join("\n"); + + return { + content: [ + { + type: "text", + text: + `✅ Cancelled ${response.length} orders for ${params.symbol}!\n\n` + + `Cancelled Orders:\n${cancelledList}\n\n` + + `Full Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + const codeMatch = errorMessage.match(/code:\s*(-?\d+)/); + const additionalHelp = + codeMatch && codeMatch[1] + ? `\n\nHint: ${getBinanceErrorMessage(parseInt(codeMatch[1]))}` + : ""; + + return { + content: [ + { + type: "text", + text: `❌ Failed to cancel all open orders: ${errorMessage}${additionalHelp}`, + }, + ], + isError: true, + }; + } + }, + ); } /** * Register all standard order tools */ export function registerBinanceUsOrderTools(server: McpServer) { - registerBinanceUsNewOrder(server); - registerBinanceUsTestOrder(server); - registerBinanceUsGetOrder(server); - registerBinanceUsCancelOrder(server); - registerBinanceUsCancelReplace(server); - registerBinanceUsCancelAllOpenOrders(server); - registerBinanceUsOpenOrders(server); - registerBinanceUsAllOrders(server); + registerBinanceUsNewOrder(server); + registerBinanceUsTestOrder(server); + registerBinanceUsGetOrder(server); + registerBinanceUsCancelOrder(server); + registerBinanceUsCancelReplace(server); + registerBinanceUsCancelAllOpenOrders(server); + registerBinanceUsOpenOrders(server); + registerBinanceUsAllOrders(server); } diff --git a/src/tools/userdata-stream/index.ts b/src/tools/userdata-stream/index.ts index 07871924..a016ba6c 100644 --- a/src/tools/userdata-stream/index.ts +++ b/src/tools/userdata-stream/index.ts @@ -2,33 +2,36 @@ // User Data Stream management for real-time account updates // These endpoints manage listen keys for WebSocket user data streams -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; -import { makeSignedRequest, BINANCE_US_CONFIG } from "../../config/binanceUsClient.js"; + +import { BINANCE_US_CONFIG, makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register User Data Stream tools for Binance.US - * + * * User Data Streams provide real-time updates for: * - Account balance updates * - Order updates (new, filled, canceled, etc.) * - Position updates - * + * * Workflow: * 1. Create a listen key using binance_us_create_listen_key * 2. Connect to WebSocket: wss://stream.binance.us:9443/ws/ * 3. Keep-alive every 30 minutes using binance_us_keepalive_listen_key * 4. Close when done using binance_us_close_listen_key - * + * * Listen keys expire after 60 minutes without a keep-alive. */ export function registerUserDataStreamTools(server: McpServer) { - // ===================================================================== - // POST /api/v3/userDataStream - Create Listen Key - // ===================================================================== - server.tool( - "binance_us_create_listen_key", - `Create a new listen key for User Data Stream WebSocket connection. + // ===================================================================== + // POST /api/v3/userDataStream - Create Listen Key + // ===================================================================== + server.registerTool( + "binance_us_create_listen_key", + { + description: `Create a new listen key for User Data Stream WebSocket connection. The listen key is used to subscribe to real-time account updates via WebSocket. Connect to: ${BINANCE_US_CONFIG.WS_URL}/ws/ @@ -45,17 +48,18 @@ The stream sends updates for: - executionReport: Order/trade updates This endpoint requires API key but does NOT require signature.`, - {}, - async () => { - try { - // This endpoint only requires API key, not signature - // But we use makeSignedRequest since it adds the API key header - const response = await makeSignedRequest("POST", "/api/v3/userDataStream", {}); - - return { - content: [{ - type: "text", - text: `Listen key created successfully! + }, + async () => { + try { + // This endpoint only requires API key, not signature + // But we use makeSignedRequest since it adds the API key header + const response = await makeSignedRequest("POST", "/api/v3/userDataStream", {}); + + return { + content: [ + { + type: "text", + text: `Listen key created successfully! Listen Key: ${response.listenKey} @@ -66,25 +70,28 @@ WebSocket URL: ${BINANCE_US_CONFIG.WS_URL}/ws/${response.listenKey} 2. Close the stream when done (use binance_us_close_listen_key) 3. The key expires after 60 minutes without keep-alive -Response: ${JSON.stringify(response, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to create listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // PUT /api/v3/userDataStream - Keep-alive Listen Key - // ===================================================================== - server.tool( - "binance_us_keepalive_listen_key", - `Extend the validity of a listen key by 60 minutes. +Response: ${JSON.stringify(response, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to create listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // PUT /api/v3/userDataStream - Keep-alive Listen Key + // ===================================================================== + server.registerTool( + "binance_us_keepalive_listen_key", + { + description: `Extend the validity of a listen key by 60 minutes. ⚠️ IMPORTANT: - Call this every 30 minutes to prevent the stream from closing @@ -92,135 +99,149 @@ Response: ${JSON.stringify(response, null, 2)}` - This resets the 60-minute expiration timer This endpoint requires API key but does NOT require signature.`, - { - listenKey: z.string().describe("The listen key to keep alive") - }, - async ({ listenKey }) => { - try { - await makeSignedRequest("PUT", "/api/v3/userDataStream", { listenKey }); - - return { - content: [{ - type: "text", - text: `Listen key extended successfully! + inputSchema: { + listenKey: z.string().describe("The listen key to keep alive"), + }, + }, + async (params: { listenKey: string }) => { + const { listenKey } = params; + try { + await makeSignedRequest("PUT", "/api/v3/userDataStream", { listenKey }); + + return { + content: [ + { + type: "text", + text: `Listen key extended successfully! Listen Key: ${listenKey} New expiration: 60 minutes from now -Remember to call this again in 30 minutes to maintain the connection.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to extend listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // DELETE /api/v3/userDataStream - Close Listen Key - // ===================================================================== - server.tool( - "binance_us_close_listen_key", - `Close a User Data Stream by invalidating the listen key. +Remember to call this again in 30 minutes to maintain the connection.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to extend listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // DELETE /api/v3/userDataStream - Close Listen Key + // ===================================================================== + server.registerTool( + "binance_us_close_listen_key", + { + description: `Close a User Data Stream by invalidating the listen key. Use this when you're done receiving real-time updates. After closing, the WebSocket connection will be terminated. This endpoint requires API key but does NOT require signature.`, - { - listenKey: z.string().describe("The listen key to close/invalidate") - }, - async ({ listenKey }) => { - try { - await makeSignedRequest("DELETE", "/api/v3/userDataStream", { listenKey }); - - return { - content: [{ - type: "text", - text: `Listen key closed successfully! + inputSchema: { + listenKey: z.string().describe("The listen key to close/invalidate"), + }, + }, + async (params: { listenKey: string }) => { + const { listenKey } = params; + try { + await makeSignedRequest("DELETE", "/api/v3/userDataStream", { listenKey }); + + return { + content: [ + { + type: "text", + text: `Listen key closed successfully! The User Data Stream has been terminated. Listen Key ${listenKey} is no longer valid. -To receive real-time updates again, create a new listen key.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to close listen key: ${errorMessage}` }], - isError: true - }; - } - } - ); - - // ===================================================================== - // Informational tool about WebSocket streams - // ===================================================================== - server.tool( - "binance_us_websocket_info", - `Get information about available WebSocket streams on Binance.US. +To receive real-time updates again, create a new listen key.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to close listen key: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================================== + // Informational tool about WebSocket streams + // ===================================================================== + server.registerTool( + "binance_us_websocket_info", + { + description: `Get information about available WebSocket streams on Binance.US. Returns details about: - Market data streams (public) - User data streams (requires listen key) - Connection URLs and limits`, - {}, - async () => { - const info = { - baseUrl: BINANCE_US_CONFIG.WS_URL, - marketDataStreams: { - description: "Public market data streams (no authentication required)", - singleStream: `${BINANCE_US_CONFIG.WS_URL}/ws/`, - multipleStreams: `${BINANCE_US_CONFIG.WS_URL}/stream?streams=/`, - availableStreams: [ - "@aggTrade - Aggregate trade stream", - "@trade - Trade stream", - "@kline_ - Kline/candlestick stream", - "@miniTicker - Individual mini ticker", - "!miniTicker@arr - All market mini tickers", - "@ticker - Individual ticker", - "!ticker@arr - All market tickers", - "@ticker_ - Rolling window ticker (1h, 4h)", - "@bookTicker - Individual book ticker", - "@depth - Partial book depth (5, 10, 20)", - "@depth@100ms - Fast partial book depth", - "@depth - Diff depth stream", - "@depth@100ms - Fast diff depth stream" - ] - }, - userDataStream: { - description: "Private account/order updates (requires listen key)", - url: `${BINANCE_US_CONFIG.WS_URL}/ws/`, - events: [ - "outboundAccountPosition - Account balance changes", - "balanceUpdate - Deposits/withdrawals", - "executionReport - Order updates" - ], - notes: [ - "Use binance_us_create_listen_key to get a listen key", - "Keep-alive every 30 minutes", - "Keys expire after 60 minutes without keep-alive" - ] - }, - limits: { - maxConnections: 5, - maxStreamsPerConnection: 1024, - messageLimit: "5 messages per second per connection" - } - }; - - return { - content: [{ - type: "text", - text: `Binance.US WebSocket Information:\n\n${JSON.stringify(info, null, 2)}` - }] - }; - } - ); + }, + async () => { + const info = { + baseUrl: BINANCE_US_CONFIG.WS_URL, + marketDataStreams: { + description: "Public market data streams (no authentication required)", + singleStream: `${BINANCE_US_CONFIG.WS_URL}/ws/`, + multipleStreams: `${BINANCE_US_CONFIG.WS_URL}/stream?streams=/`, + availableStreams: [ + "@aggTrade - Aggregate trade stream", + "@trade - Trade stream", + "@kline_ - Kline/candlestick stream", + "@miniTicker - Individual mini ticker", + "!miniTicker@arr - All market mini tickers", + "@ticker - Individual ticker", + "!ticker@arr - All market tickers", + "@ticker_ - Rolling window ticker (1h, 4h)", + "@bookTicker - Individual book ticker", + "@depth - Partial book depth (5, 10, 20)", + "@depth@100ms - Fast partial book depth", + "@depth - Diff depth stream", + "@depth@100ms - Fast diff depth stream", + ], + }, + userDataStream: { + description: "Private account/order updates (requires listen key)", + url: `${BINANCE_US_CONFIG.WS_URL}/ws/`, + events: [ + "outboundAccountPosition - Account balance changes", + "balanceUpdate - Deposits/withdrawals", + "executionReport - Order updates", + ], + notes: [ + "Use binance_us_create_listen_key to get a listen key", + "Keep-alive every 30 minutes", + "Keys expire after 60 minutes without keep-alive", + ], + }, + limits: { + maxConnections: 5, + maxStreamsPerConnection: 1024, + messageLimit: "5 messages per second per connection", + }, + }; + + return { + content: [ + { + type: "text", + text: `Binance.US WebSocket Information:\n\n${JSON.stringify(info, null, 2)}`, + }, + ], + }; + }, + ); } diff --git a/src/tools/wallet/index.ts b/src/tools/wallet/index.ts index ecd70ae0..0ac2ebf4 100644 --- a/src/tools/wallet/index.ts +++ b/src/tools/wallet/index.ts @@ -1,11 +1,13 @@ // src/tools/wallet/index.ts -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + import { z } from "zod"; + import { makeSignedRequest } from "../../config/binanceUsClient.js"; /** * Register all Wallet-related tools for Binance.US - * + * * Wallet endpoints provide access to: * - Asset configuration and network status * - Crypto withdrawals @@ -15,252 +17,307 @@ import { makeSignedRequest } from "../../config/binanceUsClient.js"; * - Deposit addresses */ export function registerWalletTools(server: McpServer) { - // ===================================================== - // binance_us_asset_config - // GET /sapi/v1/capital/config/getall - // ===================================================== - server.tool( - "binance_us_asset_config", + // ===================================================== + // binance_us_asset_config + // GET /sapi/v1/capital/config/getall + // ===================================================== + server.registerTool( + "binance_us_asset_config", + { + description: "Get details of all crypto assets including fees, withdrawal limits, and network status. Shows deposit/withdrawal enabled status per network.", - { - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ recvWindow }) => { - try { - const params: Record = {}; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/capital/config/getall", params); - - return { - content: [{ - type: "text", - text: `Asset Configuration:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get asset config: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ recvWindow }) => { + try { + const params: Record = {}; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/capital/config/getall", params); + + return { + content: [ + { + type: "text", + text: `Asset Configuration:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get asset config: ${errorMessage}` }], + isError: true, + }; + } + }, + ); - // ===================================================== - // binance_us_withdraw_crypto - // POST /sapi/v1/capital/withdraw/apply - // ===================================================== - server.tool( - "binance_us_withdraw_crypto", + // ===================================================== + // binance_us_withdraw_crypto + // POST /sapi/v1/capital/withdraw/apply + // ===================================================== + server.registerTool( + "binance_us_withdraw_crypto", + { + description: "Submit a crypto withdrawal request. Requires withdrawal permission on API key. ⚠️ This action transfers funds OUT of your account - verify address carefully!", - { - coin: z.string().describe("Asset symbol, e.g., BTC, ETH, USDT"), - network: z.string().describe("Withdrawal network, e.g., ERC20, BEP20, BTC. Ensure address type matches network!"), - address: z.string().describe("Withdrawal destination address"), - amount: z.number().describe("Withdrawal amount"), - addressTag: z.string().optional().describe("Memo/tag for coins like XRP, XMR, etc."), - withdrawOrderId: z.string().optional().describe("Client ID for the withdrawal (for your reference)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ coin, network, address, amount, addressTag, withdrawOrderId, recvWindow }) => { - try { - const params: Record = { - coin, - network, - address, - amount - }; - if (addressTag !== undefined) params.addressTag = addressTag; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("POST", "/sapi/v1/capital/withdraw/apply", params); - - return { - content: [{ - type: "text", - text: `Withdrawal request submitted successfully!\nWithdrawal ID: ${data.id}\nCoin: ${coin}\nAmount: ${amount}\nNetwork: ${network}\nAddress: ${address}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to submit withdrawal: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + coin: z.string().describe("Asset symbol, e.g., BTC, ETH, USDT"), + network: z + .string() + .describe( + "Withdrawal network, e.g., ERC20, BEP20, BTC. Ensure address type matches network!", + ), + address: z.string().describe("Withdrawal destination address"), + amount: z.number().describe("Withdrawal amount"), + addressTag: z.string().optional().describe("Memo/tag for coins like XRP, XMR, etc."), + withdrawOrderId: z + .string() + .optional() + .describe("Client ID for the withdrawal (for your reference)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, address, amount, addressTag, withdrawOrderId, recvWindow }) => { + try { + const params: Record = { + coin, + network, + address, + amount, + }; + if (addressTag !== undefined) params.addressTag = addressTag; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (recvWindow !== undefined) params.recvWindow = recvWindow; - // ===================================================== - // binance_us_withdraw_fiat - // POST /sapi/v1/fiatpayment/withdraw/apply - // ===================================================== - server.tool( - "binance_us_withdraw_fiat", + const data = await makeSignedRequest("POST", "/sapi/v1/capital/withdraw/apply", params); + + return { + content: [ + { + type: "text", + text: `Withdrawal request submitted successfully!\nWithdrawal ID: ${data.id}\nCoin: ${coin}\nAmount: ${amount}\nNetwork: ${network}\nAddress: ${address}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to submit withdrawal: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_withdraw_fiat + // POST /sapi/v1/fiatpayment/withdraw/apply + // ===================================================== + server.registerTool( + "binance_us_withdraw_fiat", + { + description: "Submit a USD withdrawal request via BITGO. ⚠️ This action transfers USD OUT of your account!", - { - paymentAccount: z.string().describe("The account to withdraw funds to"), - amount: z.number().describe("USD amount to withdraw"), - paymentMethod: z.literal("BITGO").default("BITGO").describe("Payment method (default: BITGO)"), - fiatCurrency: z.literal("USD").default("USD").describe("Fiat currency (default: USD)"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ paymentAccount, amount, paymentMethod, fiatCurrency, recvWindow }) => { - try { - const params: Record = { - paymentMethod: paymentMethod || "BITGO", - paymentAccount, - amount, - fiatCurrency: fiatCurrency || "USD" - }; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("POST", "/sapi/v1/fiatpayment/withdraw/apply", params); - - return { - content: [{ - type: "text", - text: `Fiat withdrawal submitted!\nOrder ID: ${data.orderId}\nChannel: ${data.channelCode}\nAmount: ${data.amount} ${data.currencyCode}\nStatus: ${data.orderStatus}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to submit fiat withdrawal: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + paymentAccount: z.string().describe("The account to withdraw funds to"), + amount: z.number().describe("USD amount to withdraw"), + paymentMethod: z + .literal("BITGO") + .default("BITGO") + .describe("Payment method (default: BITGO)"), + fiatCurrency: z.literal("USD").default("USD").describe("Fiat currency (default: USD)"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ paymentAccount, amount, paymentMethod, fiatCurrency, recvWindow }) => { + try { + const params: Record = { + paymentMethod: paymentMethod || "BITGO", + paymentAccount, + amount, + fiatCurrency: fiatCurrency || "USD", + }; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("POST", "/sapi/v1/fiatpayment/withdraw/apply", params); + + return { + content: [ + { + type: "text", + text: `Fiat withdrawal submitted!\nOrder ID: ${data.orderId}\nChannel: ${data.channelCode}\nAmount: ${data.amount} ${data.currencyCode}\nStatus: ${data.orderStatus}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); - // ===================================================== - // binance_us_withdraw_history - // GET /sapi/v1/capital/withdraw/history - // ===================================================== - server.tool( - "binance_us_withdraw_history", - "Get crypto withdrawal history. Filter by coin, status, or time range.", - { - coin: z.string().optional().describe("Filter by coin symbol"), - withdrawOrderId: z.string().optional().describe("Filter by client withdrawal ID"), - status: z.number().optional().describe("Status filter: 0=email sent, 1=canceled, 2=awaiting approval, 3=rejected, 4=processing, 5=failure, 6=completed"), - startTime: z.number().optional().describe("Start time in ms. Default: 90 days ago"), - endTime: z.number().optional().describe("End time in ms. Default: now"), - offset: z.number().optional().describe("Pagination offset. Default: 0"), - limit: z.number().optional().describe("Number of results. Default: 1000, Max: 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: Record = {}; - if (coin !== undefined) params.coin = coin; - if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/capital/withdraw/history", params); - - return { - content: [{ - type: "text", - text: `Withdrawal History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get withdrawal history: ${errorMessage}` }], - isError: true - }; - } - } - ); + return { + content: [{ type: "text", text: `Failed to submit fiat withdrawal: ${errorMessage}` }], + isError: true, + }; + } + }, + ); - // ===================================================== - // binance_us_deposit_history - // GET /sapi/v1/capital/deposit/hisrec - // ===================================================== - server.tool( - "binance_us_deposit_history", - "Get crypto deposit history. Filter by coin, status, or time range.", - { - coin: z.string().optional().describe("Filter by coin symbol"), - status: z.number().optional().describe("Status filter: 0=pending, 1=success, 6=credited but cannot withdraw"), - startTime: z.number().optional().describe("Start time in ms. Default: 90 days ago"), - endTime: z.number().optional().describe("End time in ms. Default: now"), - offset: z.number().optional().describe("Pagination offset. Default: 0"), - limit: z.number().optional().describe("Number of results. Default: 1000, Max: 1000"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { - try { - const params: Record = {}; - if (coin !== undefined) params.coin = coin; - if (status !== undefined) params.status = status; - if (startTime !== undefined) params.startTime = startTime; - if (endTime !== undefined) params.endTime = endTime; - if (offset !== undefined) params.offset = offset; - if (limit !== undefined) params.limit = limit; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/capital/deposit/hisrec", params); - - return { - content: [{ - type: "text", - text: `Deposit History:\n${JSON.stringify(data, null, 2)}` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get deposit history: ${errorMessage}` }], - isError: true - }; - } - } - ); + // ===================================================== + // binance_us_withdraw_history + // GET /sapi/v1/capital/withdraw/history + // ===================================================== + server.registerTool( + "binance_us_withdraw_history", + { + description: "Get crypto withdrawal history. Filter by coin, status, or time range.", + inputSchema: { + coin: z.string().optional().describe("Filter by coin symbol"), + withdrawOrderId: z.string().optional().describe("Filter by client withdrawal ID"), + status: z + .number() + .optional() + .describe( + "Status filter: 0=email sent, 1=canceled, 2=awaiting approval, 3=rejected, 4=processing, 5=failure, 6=completed", + ), + startTime: z.number().optional().describe("Start time in ms. Default: 90 days ago"), + endTime: z.number().optional().describe("End time in ms. Default: now"), + offset: z.number().optional().describe("Pagination offset. Default: 0"), + limit: z.number().optional().describe("Number of results. Default: 1000, Max: 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, withdrawOrderId, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: Record = {}; + if (coin !== undefined) params.coin = coin; + if (withdrawOrderId !== undefined) params.withdrawOrderId = withdrawOrderId; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; - // ===================================================== - // binance_us_deposit_address - // GET /sapi/v1/capital/deposit/address - // ===================================================== - server.tool( - "binance_us_deposit_address", + const data = await makeSignedRequest("GET", "/sapi/v1/capital/withdraw/history", params); + + return { + content: [ + { + type: "text", + text: `Withdrawal History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get withdrawal history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_deposit_history + // GET /sapi/v1/capital/deposit/hisrec + // ===================================================== + server.registerTool( + "binance_us_deposit_history", + { + description: "Get crypto deposit history. Filter by coin, status, or time range.", + inputSchema: { + coin: z.string().optional().describe("Filter by coin symbol"), + status: z + .number() + .optional() + .describe("Status filter: 0=pending, 1=success, 6=credited but cannot withdraw"), + startTime: z.number().optional().describe("Start time in ms. Default: 90 days ago"), + endTime: z.number().optional().describe("End time in ms. Default: now"), + offset: z.number().optional().describe("Pagination offset. Default: 0"), + limit: z.number().optional().describe("Number of results. Default: 1000, Max: 1000"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, status, startTime, endTime, offset, limit, recvWindow }) => { + try { + const params: Record = {}; + if (coin !== undefined) params.coin = coin; + if (status !== undefined) params.status = status; + if (startTime !== undefined) params.startTime = startTime; + if (endTime !== undefined) params.endTime = endTime; + if (offset !== undefined) params.offset = offset; + if (limit !== undefined) params.limit = limit; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/capital/deposit/hisrec", params); + + return { + content: [ + { + type: "text", + text: `Deposit History:\n${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get deposit history: ${errorMessage}` }], + isError: true, + }; + } + }, + ); + + // ===================================================== + // binance_us_deposit_address + // GET /sapi/v1/capital/deposit/address + // ===================================================== + server.registerTool( + "binance_us_deposit_address", + { + description: "Get a deposit address for a specific crypto asset. Use this to receive funds into your Binance.US account.", - { - coin: z.string().describe("Coin symbol to get deposit address for, e.g., BTC, ETH"), - network: z.string().optional().describe("Specific network to get address for, e.g., ERC20, BEP20"), - recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), - }, - async ({ coin, network, recvWindow }) => { - try { - const params: Record = { coin }; - if (network !== undefined) params.network = network; - if (recvWindow !== undefined) params.recvWindow = recvWindow; - - const data = await makeSignedRequest("GET", "/sapi/v1/capital/deposit/address", params); - - return { - content: [{ - type: "text", - text: `Deposit Address for ${coin}:\nAddress: ${data.address}\nTag/Memo: ${data.tag || "N/A"}\nURL: ${data.url || "N/A"}\n\n⚠️ Only send ${coin} to this address. Sending other assets may result in permanent loss.` - }] - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return { - content: [{ type: "text", text: `Failed to get deposit address: ${errorMessage}` }], - isError: true - }; - } - } - ); + inputSchema: { + coin: z.string().describe("Coin symbol to get deposit address for, e.g., BTC, ETH"), + network: z + .string() + .optional() + .describe("Specific network to get address for, e.g., ERC20, BEP20"), + recvWindow: z.number().optional().describe("The value cannot be greater than 60000"), + }, + }, + async ({ coin, network, recvWindow }) => { + try { + const params: Record = { coin }; + if (network !== undefined) params.network = network; + if (recvWindow !== undefined) params.recvWindow = recvWindow; + + const data = await makeSignedRequest("GET", "/sapi/v1/capital/deposit/address", params); + + return { + content: [ + { + type: "text", + text: `Deposit Address for ${coin}:\nAddress: ${data.address}\nTag/Memo: ${data.tag || "N/A"}\nURL: ${data.url || "N/A"}\n\n⚠️ Only send ${coin} to this address. Sending other assets may result in permanent loss.`, + }, + ], + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + + return { + content: [{ type: "text", text: `Failed to get deposit address: ${errorMessage}` }], + isError: true, + }; + } + }, + ); } diff --git a/src/utils/json.ts b/src/utils/json.ts new file mode 100644 index 00000000..da9b4ecd --- /dev/null +++ b/src/utils/json.ts @@ -0,0 +1,3 @@ +export function safeJsonStringify(value: unknown): string { + return JSON.stringify(value, (_key, v) => (typeof v === "bigint" ? v.toString() : v)); +} diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 8aa8a671..3c1783d3 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,47 +1,48 @@ // src/utils/logger.ts -type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR" +type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR"; const LOG_LEVELS: Record = { DEBUG: 0, INFO: 1, WARN: 2, - ERROR: 3 -} + ERROR: 3, +}; -const currentLevel = (process.env.LOG_LEVEL as LogLevel) || "INFO" +const currentLevel = (process.env.LOG_LEVEL as LogLevel) || "INFO"; function shouldLog(level: LogLevel): boolean { - return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel] + return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel]; } function formatMessage(level: LogLevel, message: string, ...args: unknown[]): string { - const timestamp = new Date().toISOString() - const formattedArgs = args.length > 0 ? " " + args.map(a => JSON.stringify(a)).join(" ") : "" - return `[${timestamp}] [${level}] ${message}${formattedArgs}` + const timestamp = new Date().toISOString(); + const formattedArgs = args.length > 0 ? " " + args.map((a) => JSON.stringify(a)).join(" ") : ""; + + return `[${timestamp}] [${level}] ${message}${formattedArgs}`; } const Logger = { debug: (message: string, ...args: unknown[]) => { if (shouldLog("DEBUG")) { - console.debug(formatMessage("DEBUG", message, ...args)) + console.debug(formatMessage("DEBUG", message, ...args)); } }, info: (message: string, ...args: unknown[]) => { if (shouldLog("INFO")) { - console.info(formatMessage("INFO", message, ...args)) + console.info(formatMessage("INFO", message, ...args)); } }, warn: (message: string, ...args: unknown[]) => { if (shouldLog("WARN")) { - console.warn(formatMessage("WARN", message, ...args)) + console.warn(formatMessage("WARN", message, ...args)); } }, error: (message: string, ...args: unknown[]) => { if (shouldLog("ERROR")) { - console.error(formatMessage("ERROR", message, ...args)) + console.error(formatMessage("ERROR", message, ...args)); } - } -} + }, +}; -export default Logger +export default Logger; diff --git a/tsconfig.json b/tsconfig.json index 9eb59514..ae47488a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ "outDir": "./build", "rootDir": "./src", "strict": true, + "noImplicitAny": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true,