UNPKG

@bbigu0898/copy-trading-mcp-server

Version:

跟单交易 MCP Server - 支持创建和管理复杂的跟单任务,自动跟随其他用户的交易策略

662 lines (657 loc) 59.9 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const types_js_1 = require("@modelcontextprotocol/sdk/types.js"); const client_js_1 = require("./client.js"); const types_js_2 = require("./types.js"); class CopyTradingMcpServer { server; client; constructor() { this.server = new index_js_1.Server({ name: 'copy-trading-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, }); this.client = new client_js_1.DbotCopyTradingClient(); this.setupToolHandlers(); this.setupErrorHandling(); } setupErrorHandling() { this.server.onerror = (error) => { console.error('[MCP Error]', error); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } setupToolHandlers() { this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => { return { tools: [ { name: 'create_copy_trading', description: '创建多链的跟单交易任务 - 自动跟随指定钱包地址的交易行为进行买入和卖出操作。', inputSchema: { type: 'object', properties: { enabled: { type: 'boolean', description: '任务启用状态,true/false', default: true, }, name: { type: 'string', description: '跟单任务的名称', }, chain: { type: 'string', enum: ['solana', 'ethereum', 'base', 'bsc', 'tron'], description: '链 (solana/ethereum/base/bsc/tron)', default: 'solana', }, dexFilter: { type: 'array', items: { type: 'string' }, description: '需要跟随的DEX,null表示全部跟随,填写名字表示只跟随该DEX的交易,包括:raydium_amm,raydium_clmm,raydium_cpmm,raydium_launchpad,meteora_dlmm,meteora_dyn,meteora_dyn2,meteora_bc,pump,pump_swap,moonshot,orca_wp,uniswap_v2,uniswap_v3,pancake_v2,pancake_v3,sunswap_v2,sunpump,ether_vista,okx_v2,fourmeme,boop', }, targetIds: { type: 'array', items: { type: 'string' }, description: '需要跟单的钱包地址(最多10个)', maxItems: 10, minItems: 1, }, tokenBlacklist: { type: 'array', items: { type: 'string' }, description: '当前任务的黑名单代币地址(最多20个),加入黑名单之后将不会跟买和跟卖这些代币', maxItems: 20, }, walletId: { type: 'string', description: '使用的钱包的id,可通过"钱包信息 API"获取', }, groupId: { type: 'string', description: '分组id', }, buySettings: { type: 'object', description: '买入相关设置', properties: { enabled: { type: 'boolean', default: true, description: '买入任务启用状态' }, startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: '跟随买入或卖出的启用时间 (UTC),每天在此时间之后跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: '跟随买入或卖出的停用时间 (UTC),每天在此时间之前跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, buyAmountType: { type: 'string', enum: ['fixed_amount', 'fixed_ratio', 'follow_amount'], default: 'follow_amount', description: '跟单买入类型,"fixed_amount"表示固定金额,"fixed_ratio"表示固定比例,"follow_amount"表示跟随金额' }, maxBuyAmountUI: { type: 'string', description: '跟单的最大买入金额,最小可填写0.001 SOL,0.0001 ETH,0.0001 BNB,1 TRX' }, buyRatio: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '跟随买入比例(0-10),当买入类型为fixed_ratio时生效' }, maxBalanceUI: { type: 'number', minimum: 0, default: 100, description: '止盈金额(ETH/SOL/BNB/TRX),钱包余额高于此金额时不会再跟随买入' }, reservedAmountUI: { type: 'number', minimum: 0, default: 0.01, description: '止损金额(ETH/SOL/BNB/TRX),钱包余额低于此金额时不会再跟随买入' }, targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: '在买入设置中时,表示聪明钱买入金额大于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入大于此值才会跟随卖出' }, targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: '在买入设置中时,表示聪明钱买入金额小于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入小于此值才会跟随卖出' }, minTokenMCUSD: { type: 'number', minimum: 0, default: 0, description: '最小跟单市值,只跟随买入高于此市值的代币' }, maxTokenMCUSD: { type: 'number', minimum: 0, default: 999999999, description: '最大跟单市值,只跟随买入低于此市值的代币' }, maxBuyTax: { type: 'number', minimum: 0, maximum: 1, description: '代币最大买入税率,对EVM链有效,只跟随买入税率低于此值的代币(数据来源于GoPlus,设置后会对跟单速度产生一定影响)' }, maxSellTax: { type: 'number', minimum: 0, maximum: 1, description: '代币最大卖出税率,对EVM链有效,只跟随买入税率低于此值的代币(数据来源于GoPlus,设置后会对跟单速度产生一定影响)' }, customFeeAndTip: { type: 'boolean', default: false, description: '"true"表示优先费 (priorityFee) 和贿赂费 (jitoTip) 两个字段均有效,系统将按填写的值执行交易 (null表示自动优先费/自动贿赂费),"false"表示高速模式下只有优先费 (priorityFee) 有效,防夹模式下只有贿赂费 (jitoTip) 有效,系统将自动进行分配' }, priorityFee: { type: 'string', default: '', description: '优先费 (SOL),对Solana有效,空字符串表示使用自动优先费' }, gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: '额外增加的gas (Gwei),对EVM链有效' }, maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: '基础gas超过此值时将不进行交易 (Gwei),对EVM链有效' }, jitoEnabled: { type: 'boolean', default: true, description: '"true"表示启用防夹模式 (Solana & Ethereum & Bsc)' }, jitoTip: { type: 'number', minimum: 0, default: 0.001, description: '防夹模式使用的贿赂费 (Solana)' }, maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: '最大滑点(0.00-1.00),买入时表示实际成交价格和期望价格之间的差距,卖出时表示期望价格和实际成交价格之间的差距,相差倍数=1/(1-滑点),0.5即最多接受2倍价差,1 即不限制价差' }, skipFreezableToken: { type: 'boolean', default: false, description: '"true"表示不买入冻结权限未丢弃的代币' }, skipMintableToken: { type: 'boolean', default: false, description: '"true"表示不买入mint权限未丢弃的代币' }, skipDelegatedToken: { type: 'boolean', default: false, description: '"true"表示不买入已委托的代币' }, skipNotOpensource: { type: 'boolean', default: false, description: '"true"表示不买入GoPlus定义为未开源的代币,对EVM链有效(启用后会对跟单速度产生一定影响)' }, skipHoneyPot: { type: 'boolean', default: false, description: '"true"表示不买入GoPlus定义为貔貅的代币,对EVM链有效(启用后会对跟单速度产生一定影响)' }, skipTargetIncreasePosition: { type: 'boolean', default: false, description: '"true"表示不买入聪明钱已持有的代币' }, minBurnedLp: { type: 'number', minimum: 0, maximum: 1, default: 0, description: '池子最小销毁比例 (0-1),只跟随买入流动性销毁比例大于等于此值的代币,支持Raydium(AMM) 和 Raydium(CPMM)' }, minLpUsd: { type: 'number', minimum: 0, default: 0, description: '最小流动性($),只跟随买入流动性大于等于此值的代币' }, minTokenAgeMs: { type: 'number', minimum: 0, default: 0, description: '代币最小创建时间(毫秒),只跟随买入创建时间大于等于此值的代币' }, maxTokenAgeMs: { type: 'number', minimum: 0, default: 999999999999, description: '代币最大创建时间(毫秒),只跟随买入创建时间小于等于此值的代币' }, maxTopHoldPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: '前10最大持仓比例 (0-1),只跟随买入前10持仓小于此值的代币(对Solana有效)' }, maxBuyTimesPerToken: { type: 'number', minimum: 1, default: 999, description: '7日内代币在此任务中的最大买入次数,超过此次数则不再跟买' }, maxBuyAmountPerToken: { type: 'number', minimum: 0, default: 999999, description: '7日内代币在此任务中的最大买入金额(SOL / ETH / BNB / TRX),超过此金额则不再跟买' }, buyExist: { type: 'boolean', default: false, description: '已持有代币是否继续跟随买入' }, buyOncePerWallet: { type: 'boolean', default: false, description: '"true"表示只买入一次,"false"表示不限制买入次数(只针对在DBot买入的代币)' }, concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: '并发节点数(1-3)' }, retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '失败后的重试次数(0-10)' }, }, required: ['maxBuyAmountUI'], }, sellSettings: { type: 'object', description: '卖出相关设置', properties: { enabled: { type: 'boolean', default: true, description: '卖出任务启用状态' }, startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: '跟随买入或卖出的启用时间 (UTC),每天在此时间之后跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: '跟随买入或卖出的停用时间 (UTC),每天在此时间之前跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, mode: { type: 'string', enum: ['mixed', 'only_copy', 'only_pnl'], default: 'mixed', description: '卖出模式,"mixed"表示同时启用跟随卖出和止盈止损,"only_copy"表示只启用跟随卖出,"only_pnl"表示只启用止盈止损' }, sellAmountType: { type: 'string', enum: ['all', 'follow_ratio', 'x_target_ratio'], default: 'all', description: '跟单卖出的比例,"all"表示100%卖出,"follow_ratio"表示跟随比例卖出,"x_target_ratio"表示根据聪明钱的卖出比例,固定乘以一个倍数进行卖出' }, xTargetRatio: { type: 'number', minimum: 0, maximum: 100, default: 1, description: '聪明钱卖出比例的倍数(0-100),例如填写0.5,则聪明钱卖出10%,你卖出10% × 0.5 = 5%;填写2,则聪明钱卖出10%,你卖出10% × 2 = 20%' }, sellSpeedType: { type: 'string', enum: ['fast', 'accurate'], default: 'accurate', description: '跟随卖出的速度,当mode为"only_pnl"时无效,可填写"fast"和"accurate","fast"表示速度优先,但可能导致卖出比例和聪明钱不一致,"accurate"表示准确优先,但卖出速度可能较慢' }, targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: '在买入设置中时,表示聪明钱买入金额大于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入大于此值才会跟随卖出' }, targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: '在买入设置中时,表示聪明钱买入金额小于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入小于此值才会跟随卖出' }, stopEarnPercent: { type: 'number', minimum: 0, description: '止盈百分比 (0.5表示50%),在快速买卖的type为"buy"时,和跟单的卖出设置中有效,当某个代币价格上涨超过此百分比时自动卖出,"null"表示不启用止盈' }, stopLossPercent: { type: 'number', minimum: 0, description: '止损百分比 (0.5表示50%),在快速买卖的type为"buy"时,和跟单的卖出设置中有效,当某个代币价格下跌超过此百分比时自动卖出,"null"表示不启用止损' }, stopEarnGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 6, description: '止盈分组,在快速买卖的type为"buy"时,和跟单的卖出设置中有效,最多支持设置6个,"null"表示不启用止盈,若同时设置了"stopEarnGroup"和"stopEarnPercent",则"stopEarnPercent"将失效' }, stopLossGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 6, description: '止损分组,在快速买卖的type为"buy"时,和跟单的卖出设置中有效,最多支持设置6个,"null"表示不启用止损,若同时设置了"stopLossGroup"和"stopLossPercent",则"stopLossPercent"将失效' }, trailingStopGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 1, description: '移动止盈止损分组,在快速买卖的type为"buy",以及跟单卖出模式为"mixed"或"only_pnl"时有效,当前仅支持设置1组,"null"表示不启用移动止盈止损' }, pnlOrderExpireDelta: { type: 'number', minimum: 0, maximum: 432000000, default: 43200000, description: '止盈止损任务的过期时间,最大值为432000000 (毫秒)' }, pnlOrderExpireExecute: { type: 'boolean', default: false, description: '"true"表示止盈止损任务创建后若有效期内未触发,则在任务结束时自动执行' }, pnlOrderUseMidPrice: { type: 'boolean', default: false, description: '"true"表示启用防插针模式,将使用1秒内的中间价格作为触发价,会尽可能但无法100%保证避免插针' }, sellMode: { type: 'string', enum: ['smart', 'normal'], default: 'smart', description: '卖出方式,对EVM链有效,当卖出收入低于消耗的gas时,"smart"表示不会卖出,"normal"表示继续卖出' }, migrateSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0, description: '开盘卖出比例(0.00-1.00),对Pump代币有效,0表示不自动卖' }, minDevSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0.5, description: '触发比例 (0-1),当Dev卖出超过这个比例时卖出你的代币' }, devSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: '当跟随Dev卖出任务触发时,你卖出的比例,为0表示不创建跟随Dev卖出任务' }, customFeeAndTip: { type: 'boolean', default: false, description: '"true"表示优先费 (priorityFee) 和贿赂费 (jitoTip) 两个字段均有效,系统将按填写的值执行交易 (null表示自动优先费/自动贿赂费),"false"表示高速模式下只有优先费 (priorityFee) 有效,防夹模式下只有贿赂费 (jitoTip) 有效,系统将自动进行分配' }, priorityFee: { type: 'string', default: '', description: '优先费 (SOL),对Solana有效,空字符串表示使用自动优先费' }, gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: '额外增加的gas (Gwei),对EVM链有效' }, maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: '基础gas超过此值时将不进行交易 (Gwei),对EVM链有效' }, jitoEnabled: { type: 'boolean', default: true, description: '"true"表示启用防夹模式 (Solana & Ethereum & Bsc)' }, jitoTip: { type: 'number', minimum: 0, default: 0.001, description: '防夹模式使用的贿赂费 (Solana)' }, maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: '最大滑点(0.00-1.00),买入时表示实际成交价格和期望价格之间的差距,卖出时表示期望价格和实际成交价格之间的差距,相差倍数=1/(1-滑点),0.5即最多接受2倍价差,1 即不限制价差' }, concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: '并发节点数(1-3)' }, retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '失败后的重试次数(0-10)' }, }, }, }, required: ['name', 'targetIds', 'buySettings', 'sellSettings'], }, }, { name: 'edit_copy_trading', description: '编辑跟单交易任务。只需要提供要修改的字段和必需字段(id, enabled, name, chain, targetIds, buySettings, sellSettings),无需重新输入所有字段。', inputSchema: { type: 'object', properties: { id: { type: 'string', description: '跟单任务id', }, enabled: { type: 'boolean', description: '任务启用状态,true/false', }, name: { type: 'string', description: '跟单任务的名称', }, chain: { type: 'string', enum: ['solana', 'ethereum', 'base', 'bsc', 'tron'], description: '链 (solana/ethereum/base/bsc/tron)', }, dexFilter: { type: 'array', items: { type: 'string' }, description: '需要跟随的DEX,null表示全部跟随,填写名字表示只跟随该DEX的交易,包括:raydium_amm,raydium_clmm,raydium_cpmm,raydium_launchpad,meteora_dlmm,meteora_dyn,meteora_dyn2,meteora_bc,pump,pump_swap,moonshot,orca_wp,uniswap_v2,uniswap_v3,pancake_v2,pancake_v3,sunswap_v2,sunpump,ether_vista,okx_v2,fourmeme,boop', }, targetIds: { type: 'array', items: { type: 'string' }, description: '需要跟单的钱包地址(最多10个)', maxItems: 10, minItems: 1, }, tokenBlacklist: { type: 'array', items: { type: 'string' }, description: '当前任务的黑名单代币地址(最多20个),加入黑名单之后将不会跟买和跟卖这些代币', maxItems: 20, }, walletId: { type: 'string', description: '使用的钱包的id,可通过"钱包信息 API"获取', }, groupId: { type: 'string', description: '分组id', }, buySettings: { type: 'object', description: '买入相关设置', properties: { enabled: { type: 'boolean', default: true, description: '买入任务启用状态' }, startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: '跟随买入或卖出的启用时间 (UTC),每天在此时间之后跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: '跟随买入或卖出的停用时间 (UTC),每天在此时间之前跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, buyAmountType: { type: 'string', enum: ['fixed_amount', 'fixed_ratio', 'follow_amount'], default: 'follow_amount', description: '跟单买入类型,"fixed_amount"表示固定金额,"fixed_ratio"表示固定比例,"follow_amount"表示跟随金额' }, maxBuyAmountUI: { type: 'string', description: '跟单的最大买入金额,最小可填写0.001 SOL,0.0001 ETH,0.0001 BNB,1 TRX' }, buyRatio: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '跟随买入比例(0-10),当买入类型为fixed_ratio时生效' }, maxBalanceUI: { type: 'number', minimum: 0, default: 100, description: '止盈金额(ETH/SOL/BNB/TRX),钱包余额高于此金额时不会再跟随买入' }, reservedAmountUI: { type: 'number', minimum: 0, default: 0.01, description: '止损金额(ETH/SOL/BNB/TRX),钱包余额低于此金额时不会再跟随买入' }, targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: '在买入设置中时,表示聪明钱买入金额大于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入大于此值才会跟随卖出' }, targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: '在买入设置中时,表示聪明钱买入金额小于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入小于此值才会跟随卖出' }, minTokenMCUSD: { type: 'number', minimum: 0, default: 0, description: '最小跟单市值,只跟随买入高于此市值的代币' }, maxTokenMCUSD: { type: 'number', minimum: 0, default: 999999999, description: '最大跟单市值,只跟随买入低于此市值的代币' }, maxBuyTax: { type: 'number', minimum: 0, maximum: 1, description: '代币最大买入税率,对EVM链有效,只跟随买入税率低于此值的代币(数据来源于GoPlus,设置后会对跟单速度产生一定影响)' }, maxSellTax: { type: 'number', minimum: 0, maximum: 1, description: '代币最大卖出税率,对EVM链有效,只跟随买入税率低于此值的代币(数据来源于GoPlus,设置后会对跟单速度产生一定影响)' }, customFeeAndTip: { type: 'boolean', default: false, description: '"true"表示优先费 (priorityFee) 和贿赂费 (jitoTip) 两个字段均有效,系统将按填写的值执行交易 (null表示自动优先费/自动贿赂费),"false"表示高速模式下只有优先费 (priorityFee) 有效,防夹模式下只有贿赂费 (jitoTip) 有效,系统将自动进行分配' }, priorityFee: { type: 'string', default: '', description: '优先费 (SOL),对Solana有效,空字符串表示使用自动优先费' }, gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: '额外增加的gas (Gwei),对EVM链有效' }, maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: '基础gas超过此值时将不进行交易 (Gwei),对EVM链有效' }, jitoEnabled: { type: 'boolean', default: true, description: '"true"表示启用防夹模式 (Solana & Ethereum & Bsc)' }, jitoTip: { type: 'number', minimum: 0, default: 0.001, description: '防夹模式使用的贿赂费 (Solana)' }, maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: '最大滑点(0.00-1.00),买入时表示实际成交价格和期望价格之间的差距,卖出时表示期望价格和实际成交价格之间的差距,相差倍数=1/(1-滑点),0.5即最多接受2倍价差,1 即不限制价差' }, skipFreezableToken: { type: 'boolean', default: false, description: '"true"表示不买入冻结权限未丢弃的代币' }, skipMintableToken: { type: 'boolean', default: false, description: '"true"表示不买入mint权限未丢弃的代币' }, skipDelegatedToken: { type: 'boolean', default: false, description: '"true"表示不买入已委托的代币' }, skipNotOpensource: { type: 'boolean', default: false, description: '"true"表示不买入GoPlus定义为未开源的代币,对EVM链有效(启用后会对跟单速度产生一定影响)' }, skipHoneyPot: { type: 'boolean', default: false, description: '"true"表示不买入GoPlus定义为貔貅的代币,对EVM链有效(启用后会对跟单速度产生一定影响)' }, skipTargetIncreasePosition: { type: 'boolean', default: false, description: '"true"表示不买入聪明钱已持有的代币' }, minBurnedLp: { type: 'number', minimum: 0, maximum: 1, default: 0, description: '池子最小销毁比例 (0-1),只跟随买入流动性销毁比例大于等于此值的代币,支持Raydium(AMM) 和 Raydium(CPMM)' }, minLpUsd: { type: 'number', minimum: 0, default: 0, description: '最小流动性($),只跟随买入流动性大于等于此值的代币' }, minTokenAgeMs: { type: 'number', minimum: 0, default: 0, description: '代币最小创建时间(毫秒),只跟随买入创建时间大于等于此值的代币' }, maxTokenAgeMs: { type: 'number', minimum: 0, default: 999999999999, description: '代币最大创建时间(毫秒),只跟随买入创建时间小于等于此值的代币' }, maxTopHoldPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: '前10最大持仓比例 (0-1),只跟随买入前10持仓小于此值的代币(对Solana有效)' }, maxBuyTimesPerToken: { type: 'number', minimum: 1, default: 999, description: '7日内代币在此任务中的最大买入次数,超过此次数则不再跟买' }, maxBuyAmountPerToken: { type: 'number', minimum: 0, default: 999999, description: '7日内代币在此任务中的最大买入金额(SOL / ETH / BNB / TRX),超过此金额则不再跟买' }, buyExist: { type: 'boolean', default: false, description: '已持有代币是否继续跟随买入' }, buyOncePerWallet: { type: 'boolean', default: false, description: '"true"表示只买入一次,"false"表示不限制买入次数(只针对在DBot买入的代币)' }, concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: '并发节点数(1-3)' }, retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '失败后的重试次数(0-10)' }, }, }, sellSettings: { type: 'object', description: '卖出相关设置', properties: { enabled: { type: 'boolean', default: true, description: '卖出任务启用状态' }, startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: '跟随买入或卖出的启用时间 (UTC),每天在此时间之后跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: '跟随买入或卖出的停用时间 (UTC),每天在此时间之前跟买或跟卖才会执行,只能填写0-23之间的整数,例如10,表示UTC时间的10:00' }, mode: { type: 'string', enum: ['mixed', 'only_copy', 'only_pnl'], default: 'mixed', description: '卖出模式,"mixed"表示同时启用跟随卖出和止盈止损,"only_copy"表示只启用跟随卖出,"only_pnl"表示只启用止盈止损' }, sellAmountType: { type: 'string', enum: ['all', 'follow_ratio', 'x_target_ratio'], default: 'all', description: '跟单卖出的比例,"all"表示100%卖出,"follow_ratio"表示跟随比例卖出,"x_target_ratio"表示根据聪明钱的卖出比例,固定乘以一个倍数进行卖出' }, xTargetRatio: { type: 'number', minimum: 0, maximum: 100, default: 1, description: '聪明钱卖出比例的倍数(0-100),例如填写0.5,则聪明钱卖出10%,你卖出10% × 0.5 = 5%;填写2,则聪明钱卖出10%,你卖出10% × 2 = 20%' }, sellSpeedType: { type: 'string', enum: ['fast', 'accurate'], default: 'accurate', description: '跟随卖出的速度,当mode为"only_pnl"时无效,可填写"fast"和"accurate","fast"表示速度优先,但可能导致卖出比例和聪明钱不一致,"accurate"表示准确优先,但卖出速度可能较慢' }, targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: '在买入设置中时,表示聪明钱买入金额大于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入大于此值才会跟随卖出' }, targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: '在买入设置中时,表示聪明钱买入金额小于此值时才会跟随买入;在卖出设置中时,表示聪明钱卖出收入小于此值才会跟随卖出' }, stopEarnPercent: { type: 'number', minimum: 0, description: '止盈百分比 (0.5表示50%),在快速买卖的type为"buy"时,和跟单的卖出设置中有效,当某个代币价格上涨超过此百分比时自动卖出,"null"表示不启用止盈' }, stopLossPercent: { type: 'number', minimum: 0, description: '止损百分比 (0.5表示50%),在快速买卖的type为"buy"时,和跟单的卖出设置中有效,当某个代币价格下跌超过此百分比时自动卖出,"null"表示不启用止损' }, stopEarnGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 6, description: '止盈分组,在快速买卖的type为"buy"时,和跟单的卖出设置中有效,最多支持设置6个,"null"表示不启用止盈,若同时设置了"stopEarnGroup"和"stopEarnPercent",则"stopEarnPercent"将失效' }, stopLossGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 6, description: '止损分组,在快速买卖的type为"buy"时,和跟单的卖出设置中有效,最多支持设置6个,"null"表示不启用止损,若同时设置了"stopLossGroup"和"stopLossPercent",则"stopLossPercent"将失效' }, trailingStopGroup: { type: 'array', items: { type: 'object', properties: { pricePercent: { type: 'number', minimum: 0, maximum: 1, description: '价格涨跌百分比 (0.5表示50%)或回撤比例,当在止盈分组里时,表示上涨多少卖出,当在止损分组里时,表示下跌多少卖出,在移动止盈止损分组里,表示回撤比例(不能大于等于1)' }, amountPercent: { type: 'number', minimum: 0, maximum: 1, description: '卖出比例 (0-1,0.5表示50%),例如涨100%卖50%,涨200%全卖,卖出比例需要设置为0.5和1,而不是0.5和0.5' }, }, required: ['pricePercent', 'amountPercent'], }, maxItems: 1, description: '移动止盈止损分组,在快速买卖的type为"buy",以及跟单卖出模式为"mixed"或"only_pnl"时有效,当前仅支持设置1组,"null"表示不启用移动止盈止损' }, pnlOrderExpireDelta: { type: 'number', minimum: 0, maximum: 432000000, default: 43200000, description: '止盈止损任务的过期时间,最大值为432000000 (毫秒)' }, pnlOrderExpireExecute: { type: 'boolean', default: false, description: '"true"表示止盈止损任务创建后若有效期内未触发,则在任务结束时自动执行' }, pnlOrderUseMidPrice: { type: 'boolean', default: false, description: '"true"表示启用防插针模式,将使用1秒内的中间价格作为触发价,会尽可能但无法100%保证避免插针' }, sellMode: { type: 'string', enum: ['smart', 'normal'], default: 'smart', description: '卖出方式,对EVM链有效,当卖出收入低于消耗的gas时,"smart"表示不会卖出,"normal"表示继续卖出' }, migrateSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0, description: '开盘卖出比例(0.00-1.00),对Pump代币有效,0表示不自动卖' }, minDevSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0.5, description: '触发比例 (0-1),当Dev卖出超过这个比例时卖出你的代币' }, devSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: '当跟随Dev卖出任务触发时,你卖出的比例,为0表示不创建跟随Dev卖出任务' }, customFeeAndTip: { type: 'boolean', default: false, description: '"true"表示优先费 (priorityFee) 和贿赂费 (jitoTip) 两个字段均有效,系统将按填写的值执行交易 (null表示自动优先费/自动贿赂费),"false"表示高速模式下只有优先费 (priorityFee) 有效,防夹模式下只有贿赂费 (jitoTip) 有效,系统将自动进行分配' }, priorityFee: { type: 'string', default: '', description: '优先费 (SOL),对Solana有效,空字符串表示使用自动优先费' }, gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: '额外增加的gas (Gwei),对EVM链有效' }, maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: '基础gas超过此值时将不进行交易 (Gwei),对EVM链有效' }, jitoEnabled: { type: 'boolean', default: true, description: '"true"表示启用防夹模式 (Solana & Ethereum & Bsc)' }, jitoTip: { type: 'number', minimum: 0, default: 0.001, description: '防夹模式使用的贿赂费 (Solana)' }, maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: '最大滑点(0.00-1.00),买入时表示实际成交价格和期望价格之间的差距,卖出时表示期望价格和实际成交价格之间的差距,相差倍数=1/(1-滑点),0.5即最多接受2倍价差,1 即不限制价差' }, concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: '并发节点数(1-3)' }, retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: '失败后的重试次数(0-10)' }, }, }, }, required: ['id', 'enabled', 'name', 'chain', 'targetIds', 'buySettings', 'sellSettings'], }, }, { name: 'switch_copy_trading', description: '开关跟单交易任务', inputSchema: { type: 'object', properties: { id: { type: 'string', description: '跟单任务ID', }, enabled: { type: 'boolean', description: '任务启用状态,true/false', }, closePnlOrder: { type: 'boolean', description: '是否同时关闭跟单任务创建的所有止盈止损任务,默认false,表示不关闭(当"enabled"为false时有效)', default: false, }, }, required: ['id', 'enabled'], }, }, { name: 'delete_copy_trading', description: '删除跟单交易任务', inputSchema: { type: 'object', properties: { id: { type: 'string', description: '跟单任务ID', }, deletePnlOrder: { type: 'boolean', description: '是否同时删除此跟单任务创建的所有止盈止损任务', default: false, }, }, required: ['id'], }, }, { name: 'get_copy_trading_tasks', description: '获取跟单任务列表', inputSchema: { type: 'object', properties: { page: { type: 'number', description: '页码', default: 0, }, size: { type: 'number', description: '每页数量', default: 20, maximum: 100, }, }, }, }, ], }; }); this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'create_copy_trading': return await this.handleCreateCopyTrading(args); case 'edit_copy_trading': return await this.handleEditCopyTrading(args); case 'switch_copy_trading': return await this.handleSwitchCopyTrading(args); case 'delete_copy_trading': return await this.handleDeleteCopyTrading(args); case 'get_copy_trading_tasks': return await this.handleGetCopyTradingTasks(args); default: throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `未知工具: ${name}`); } } catch (error) { if (error instanceof types_js_1.McpError) { throw error; } const errorMessage = error instanceof Error ? error.message : String(error); console.error(`工具 ${name} 执行错误:`, error); throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `执行 ${name} 时发生错误: ${errorMessage}`); } }); } async handleCreateCopyTrading(args) { try { // 如果没有提供 walletId,使用环境变量 if (!args.walletId) { args.walletId = process.env.DBOT_WALLET_ID; if (!args.walletId) { throw new Error('钱包ID未提供:请在参数中指定 walletId 或设置环境变量 DBOT_WALLET_ID'); } } // 验证请求参数 const validatedRequest = types_js_2.CreateCopyTradingRequestSchema.parse(args); const response = await this.client.createCopyTrading(validatedRequest); if (response.err) { throw new Error(`API错误: ${JSON.stringify(response)}`); } return { content: [ { type: 'text', text: `✅ 跟单任务创建成功! 📋 任务信息: - 任务ID: ${response.res.id} - 任务名称: ${args.name} - 链: ${args.chain || 'solana'} - 跟单地址: ${args.targetIds.join(', ')} - 状态: ${args.enabled !== false ? '启用' : '禁用'} - 钱包ID: ${args.walletId} ${args.groupId ? `- 分组ID: ${args.groupId}` : ''} 🛒 买入设置: - 启用: ${args.buySettings.enabled ? '是' : '否'} - 最大买入金额: ${args.buySettings.maxBuyAmountUI} - 买入类型: ${args.buySettings.buyAmountType || 'follow_amount'} 💰 卖出设置: - 启用: ${args.sellSettings.enabled ? '是' : '否'} - 模式: ${args.sellSettings.mode || 'mixed'}`, }, ], }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `创建跟单任务失败: ${error instanceof Error ? error.message : String(error)}`); } } async handleEditCopyTrading(args) { try { // 如果没有提供 walletId,使用环境变量 if (!args.walletId) { args.walletId = process.env.DBOT_WALLET_ID; if (!args.walletId) { throw new Error('钱包ID未提供:请在参数中指定 walletId 或设置环境变量 DBOT_WALLET_ID'); } } const validatedRequest = types_js_2.EditCopyTradingRequestSchema.parse(args); const response = await this.client.editCopyTrading(validatedRequest); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `编辑跟单任务失败: ${error instanceof Error ? error.message : String(error)}`); } } async handleSwitchCopyTrading(args) { try { const validatedRequest = types_js_2.SwitchCopyTradingRequestSchema.parse(args); const response = await this.client.switchCopyTrading(validatedRequest); if (response.err) { throw new Error(`API错误: ${JSON.stringify(response)}`); } return { content: [ { type: 'text', text: `✅ 跟单任务状态切换成功! 📋 任务信息: - 任务ID: ${args.id} - 新状态: ${args.enabled ? '启用' : '禁用'} ${args.closePnlOrder ? '- 同时关闭所有止盈止损任务' : ''}`, }, ], }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `切换跟单任务状态失败: ${error instanceof Error ? error.message : String(error)}`); } } async handleDeleteCopyTrading(args) { try { const validatedRequest = types_js_2.DeleteCopyTradingRequestSchema.parse(args); const response = await this.client.deleteCopyTrading(validatedRequest); if (response.err) { throw new Error(`API错误: ${JSON.stringify(response)}`); } return { content: [ { type: 'text', text: `✅ 跟单任务删除成功! 📋 删除信息: - 任务ID: ${args.id} ${args.deletePnlOrder ? '- 同时删除所有关联的止盈止损任务' : '- 保留关联的止盈止损任务'}`, }, ], }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `删除跟单任务失败: ${error instanceof Error ? error.message : String(error)}`); } } async handleGetCopyTradingTasks(args) { try { const page = args.page || 0; const size = Math.min(args.size || 20, 100); const response = await this.client.getCopyTradingTasks(page, size); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `获取跟单任务列表失败: ${error instanceof Error ? error.message : String(error)}`); } } async run() { const transport = new stdio_js_1.StdioServerTransport(); await this.server.connect(transport); console.error('Copy Trading MCP 服务器已启动'); } } async function main() { const server = new CopyTradingMcpServer(); await server.run(); } // @ts-ignore if (require.main === module) { main().catch((error) => { console.error('服务器启动失败:', error); process.exit(1); }); } //# sourceMappingURL=index.js.map