@bbigu0898/copy-trading-mcp-server
Version:
跟单交易 MCP Server - 支持创建和管理复杂的跟单任务,自动跟随其他用户的交易策略
662 lines (657 loc) • 59.9 kB
JavaScript
#!/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