@potswap_io/mcp 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/defiTools.d.ts +6 -0
- package/dist/defiTools.js +108 -0
- package/dist/server.d.ts +4 -1
- package/dist/server.js +26 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -73,12 +73,15 @@ Use a dedicated agent wallet with only the funds you want the agent to control.
|
|
|
73
73
|
| `get_token {mint}` | Price, mcap, liquidity, holders, audit data, **risk badges** (`riskLevel` 0 safe → 3 danger) |
|
|
74
74
|
| `get_trending {kind}` | `new`, `trending`, `top`, `graduating` lists |
|
|
75
75
|
| `get_quote {inputMint, outputMint, amount}` | Best route, fee, impact, router. `amount` is in UI units (1 = 1 SOL) |
|
|
76
|
-
| `swap {…, confirm: true}` | Executes at the best route and returns the signature, amounts, fee and POT points |
|
|
76
|
+
| `swap {…, confirm: true, route?, opId?}` | Executes at the best route and returns the signature, amounts, fee and POT points. `route: direct` swaps on a Raydium CPMM pool built and validated locally (same fee); `opId` makes retries safe |
|
|
77
|
+
| `get_operation {id?}` | State of an idempotent swap (pending / sent / ok / failed / unknown) |
|
|
77
78
|
| `get_balances {wallet?}` | SOL + SPL balances with USD |
|
|
78
79
|
| `get_positions {wallet?}` | Holdings with USD value, average cost, unrealised and realised PnL (from swap history) |
|
|
79
80
|
| `get_points {wallet?}` | Season 1 points, POT allocated / claimable, next unlock |
|
|
80
81
|
| `get_leaderboard` | Top wallets by fee paid |
|
|
81
82
|
| `observe_publish`, `observe_query`, `observe_verify`, `observe_consume` | Signed, slot-anchored market observations on the open index: publish with your wallet, read everyone's with a per-publisher median, verify locally, record that you used one (earns the publisher Season 2 rewards). `limit_order_create` can trigger on the observation median (`priceSource: observations`) |
|
|
83
|
+
| `lend_markets`, `lend_positions`, `lend_deposit`, `lend_withdraw` | Jupiter Lend Earn: markets with APY, your positions, deposit (fee, points) and free withdrawal |
|
|
84
|
+
| `lp_pools`, `lp_position`, `lp_deposit`, `lp_withdraw` | Raydium CPMM liquidity: pools with live reserves, your share, add (fee, points) and remove (free) |
|
|
82
85
|
| `get_launch_status` | Launch-pool meter (SOL / 500 target, from chain), season and day, fee split, unclaimed reward balances and the public claim ladder |
|
|
83
86
|
| `get_price_history {mint, timeframe, limit}` | OHLCV candles from the token's top pool (`1m`…`1d`) |
|
|
84
87
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { NO_WALLET, executeLend, executeLpDeposit, executeLpWithdraw, lpPools, lpPosition, normalizeMarkets, normalizePositions, redact, redactValue } from '@potswap_io/sdk';
|
|
3
|
+
const ok = (data, summary) => ({ content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data) });
|
|
4
|
+
const fail = (message, extra = {}) => ({ content: [{ type: 'text', text: redact(message) }], structuredContent: redactValue({ error: message, ...extra }), isError: true });
|
|
5
|
+
const MINT = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/);
|
|
6
|
+
export function registerDefiTools(server, deps) {
|
|
7
|
+
const { trade } = deps;
|
|
8
|
+
const api = trade.api;
|
|
9
|
+
const walletOr = (w) => w ?? trade.signer?.publicKey ?? null;
|
|
10
|
+
const outcome = (r, verb) => {
|
|
11
|
+
switch (r.kind) {
|
|
12
|
+
case 'no-wallet':
|
|
13
|
+
case 'refused':
|
|
14
|
+
case 'failed': return fail(r.message, 'signature' in r && r.signature ? { signature: r.signature, explorerUrl: r.explorerUrl } : {});
|
|
15
|
+
case 'plan': return ok({ confirmRequired: true, plan: r.plan }, `Plan (confirm=true to execute): ${JSON.stringify(r.plan)}`);
|
|
16
|
+
case 'dry-run': return ok({ dryRun: true, plan: r.plan }, `DRY RUN, nothing signed: ${JSON.stringify(r.plan)}`);
|
|
17
|
+
case 'ok': return ok(r.result, `${verb}. ${String(r.result.explorerUrl)}${'feeNote' in r.result && r.result.feeNote ? `\n${String(r.result.feeNote)}` : ''}`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
server.registerTool('lend_markets', {
|
|
21
|
+
title: 'Lending markets (Jupiter Lend Earn)',
|
|
22
|
+
description: 'Earn markets with supply APY and total deposits. No wallet needed.',
|
|
23
|
+
inputSchema: {},
|
|
24
|
+
}, async () => {
|
|
25
|
+
try {
|
|
26
|
+
const markets = normalizeMarkets(await api.lendTokens());
|
|
27
|
+
return ok({ markets }, markets.map((m) => `${m.assetSymbol.padEnd(6)} ${m.supplyApyPct.toFixed(2)}% APY${m.rewardsApyPct ? ` (+${m.rewardsApyPct.toFixed(2)}% rewards)` : ''} · ${m.totalAssets.toLocaleString(undefined, { maximumFractionDigits: 0 })} deposited · mint ${m.assetMint}`).join('\n'));
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
return fail(e instanceof Error ? e.message : String(e));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
server.registerTool('lend_positions', {
|
|
34
|
+
title: 'Lending positions',
|
|
35
|
+
description: 'The wallet\'s Jupiter Lend Earn positions: shares, underlying amount, USD.',
|
|
36
|
+
inputSchema: { wallet: MINT.optional() },
|
|
37
|
+
}, async ({ wallet }) => {
|
|
38
|
+
const w = walletOr(wallet);
|
|
39
|
+
if (!w)
|
|
40
|
+
return fail(NO_WALLET);
|
|
41
|
+
try {
|
|
42
|
+
const positions = normalizePositions(await api.lendPositions([w]));
|
|
43
|
+
return ok({ wallet: w, positions }, positions.length ? positions.map((p) => `${p.assetSymbol}: ${p.underlying}${p.underlyingUsd !== undefined ? ` ($${p.underlyingUsd.toFixed(2)})` : ''} · ${p.shares} ${p.symbol}`).join('\n') : 'No lending positions.');
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
return fail(e instanceof Error ? e.message : String(e));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
server.registerTool('lend_deposit', {
|
|
50
|
+
title: 'Deposit into Jupiter Lend Earn',
|
|
51
|
+
description: 'Deposits a token into its Earn market. Requires confirm=true; without it returns the plan. Pays the Potswap fee (sent after the deposit confirms) and earns points. Subject to POTSWAP_MAX_TRADE_SOL and POTSWAP_ALLOWED_TOKENS.',
|
|
52
|
+
inputSchema: { mint: MINT, amount: z.number().positive(), confirm: z.boolean().default(false) },
|
|
53
|
+
}, async (a) => outcome(await executeLend(trade, { action: 'deposit', mint: a.mint, amount: a.amount, confirm: a.confirm }), 'Deposited'));
|
|
54
|
+
server.registerTool('lend_withdraw', {
|
|
55
|
+
title: 'Withdraw from Jupiter Lend Earn',
|
|
56
|
+
description: 'Withdraws an amount (or everything with all=true) from an Earn market. Free. Requires confirm=true.',
|
|
57
|
+
inputSchema: { mint: MINT, amount: z.number().positive().optional(), all: z.boolean().default(false), confirm: z.boolean().default(false) },
|
|
58
|
+
}, async (a) => {
|
|
59
|
+
if (!a.all && a.amount === undefined)
|
|
60
|
+
return fail('Give amount or all=true. No funds were debited.');
|
|
61
|
+
return outcome(await executeLend(trade, { action: 'withdraw', mint: a.mint, amount: a.all ? 'all' : a.amount, confirm: a.confirm }), 'Withdrew');
|
|
62
|
+
});
|
|
63
|
+
server.registerTool('lp_pools', {
|
|
64
|
+
title: 'Raydium CPMM pools for a pair',
|
|
65
|
+
description: 'CPMM pools with live reserves (net of protocol fees), LP supply, trade fee and TVL. No wallet needed.',
|
|
66
|
+
inputSchema: { mintA: MINT, mintB: MINT },
|
|
67
|
+
}, async ({ mintA, mintB }) => {
|
|
68
|
+
if (!trade.rpc?.getAccountsData)
|
|
69
|
+
return fail('Liquidity operations need an RPC connection.');
|
|
70
|
+
try {
|
|
71
|
+
const pools = await lpPools(api, trade.rpc.getAccountsData.bind(trade.rpc), mintA, mintB);
|
|
72
|
+
return ok({ pools }, pools.length ? pools.map((p) => `${p.poolId}: ${p.reserve0} ${p.token0Mint.slice(0, 4)}… / ${p.reserve1} ${p.token1Mint.slice(0, 4)}… · fee ${p.tradeFeeBps} bps${p.tvlUsd ? ` · TVL $${p.tvlUsd.toFixed(0)}` : ''}${p.swapEnabled ? '' : ' · swaps disabled'}`).join('\n') : 'No CPMM pool for this pair.');
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return fail(e instanceof Error ? e.message : String(e));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
server.registerTool('lp_position', {
|
|
79
|
+
title: 'LP position in a CPMM pool',
|
|
80
|
+
description: 'LP token balance for a pool and the token amounts it represents at current reserves.',
|
|
81
|
+
inputSchema: { poolId: MINT, wallet: MINT.optional() },
|
|
82
|
+
}, async ({ poolId, wallet }) => {
|
|
83
|
+
const w = walletOr(wallet);
|
|
84
|
+
if (!w)
|
|
85
|
+
return fail(NO_WALLET);
|
|
86
|
+
if (!trade.rpc?.getAccountsData)
|
|
87
|
+
return fail('Liquidity operations need an RPC connection.');
|
|
88
|
+
try {
|
|
89
|
+
const pos = await lpPosition(trade.rpc.getAccountsData.bind(trade.rpc), await trade.balances(w), poolId);
|
|
90
|
+
if (!pos)
|
|
91
|
+
return fail('Pool not found or not a Raydium CPMM pool.');
|
|
92
|
+
return ok({ wallet: w, ...pos, lpBalanceRaw: pos.lpBalanceRaw.toString() }, `${pos.lpBalance} LP (${pos.sharePct.toFixed(4)}% of the pool) ≈ ${pos.amount0} ${pos.token0Mint.slice(0, 4)}… + ${pos.amount1} ${pos.token1Mint.slice(0, 4)}…`);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
return fail(e instanceof Error ? e.message : String(e));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
server.registerTool('lp_deposit', {
|
|
99
|
+
title: 'Add liquidity to a CPMM pool',
|
|
100
|
+
description: 'Deposits `amount` of `mint` (one of the pool tokens) plus the matching amount of the other token for LP tokens. The Potswap fee comes off the given side in the same transaction. Requires confirm=true; without it returns the plan.',
|
|
101
|
+
inputSchema: { poolId: MINT, mint: MINT, amount: z.number().positive(), maxSlippageBps: z.number().int().min(1).max(5000).optional(), confirm: z.boolean().default(false) },
|
|
102
|
+
}, async (a) => outcome(await executeLpDeposit(trade, { poolId: a.poolId, mint: a.mint, amount: a.amount, slippageBps: a.maxSlippageBps, confirm: a.confirm }), 'Liquidity added'));
|
|
103
|
+
server.registerTool('lp_withdraw', {
|
|
104
|
+
title: 'Remove liquidity from a CPMM pool',
|
|
105
|
+
description: 'Burns LP tokens (an amount or a percentage of the balance) for both pool tokens. Free. Requires confirm=true.',
|
|
106
|
+
inputSchema: { poolId: MINT, lpAmount: z.number().positive().optional(), pct: z.number().min(0.01).max(100).optional(), maxSlippageBps: z.number().int().min(1).max(5000).optional(), confirm: z.boolean().default(false) },
|
|
107
|
+
}, async (a) => outcome(await executeLpWithdraw(trade, { poolId: a.poolId, lpAmount: a.lpAmount, pct: a.pct, slippageBps: a.maxSlippageBps, confirm: a.confirm }), 'Liquidity removed'));
|
|
108
|
+
}
|
package/dist/server.d.ts
CHANGED
|
@@ -5,9 +5,10 @@ import { type BalancesFn } from '@potswap_io/sdk';
|
|
|
5
5
|
import { type Signer } from '@potswap_io/sdk';
|
|
6
6
|
import { type TxRpc } from './agentTools.js';
|
|
7
7
|
import type { Rpc } from '@potswap_io/sdk';
|
|
8
|
+
import { type OpsStore } from '@potswap_io/sdk';
|
|
8
9
|
import type { StrategyStore } from '@potswap_io/sdk';
|
|
9
10
|
import type { Scheduler } from '@potswap_io/sdk';
|
|
10
|
-
export declare const VERSION = "0.
|
|
11
|
+
export declare const VERSION = "0.8.0";
|
|
11
12
|
export interface ServerDeps {
|
|
12
13
|
config?: Config;
|
|
13
14
|
signer?: Signer | null;
|
|
@@ -22,6 +23,8 @@ export interface ServerDeps {
|
|
|
22
23
|
txRpc?: TxRpc;
|
|
23
24
|
/** Current slot for observation anchoring; injectable for tests (P15). */
|
|
24
25
|
getSlot?: () => Promise<number>;
|
|
26
|
+
/** Idempotent operation records (P14.3); defaults to a file store in the state dir. */
|
|
27
|
+
ops?: OpsStore;
|
|
25
28
|
}
|
|
26
29
|
export declare function createServer(deps?: ServerDeps): McpServer;
|
|
27
30
|
export { SOL_MINT, USDC_MINT };
|
package/dist/server.js
CHANGED
|
@@ -11,7 +11,9 @@ import { riskBadges, riskLevel } from '@potswap_io/sdk';
|
|
|
11
11
|
import { registerStrategyTools } from './strategies/tools.js';
|
|
12
12
|
import { registerAgentTools } from './agentTools.js';
|
|
13
13
|
import { registerObservationTools } from './observationTools.js';
|
|
14
|
-
|
|
14
|
+
import { registerDefiTools } from './defiTools.js';
|
|
15
|
+
import { FileOpsStore, rpcFromConnection } from '@potswap_io/sdk';
|
|
16
|
+
export const VERSION = '0.8.0';
|
|
15
17
|
const ok = (data, summary) => ({
|
|
16
18
|
content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data),
|
|
17
19
|
});
|
|
@@ -23,7 +25,7 @@ export function createServer(deps = {}) {
|
|
|
23
25
|
const signer = deps.signer !== undefined ? deps.signer : loadSigner({ privateKey: config.privateKey, keypairPath: config.keypairPath, stateDir: config.stateDir });
|
|
24
26
|
const api = new PotswapApi(config.apiBase, deps.fetchFn);
|
|
25
27
|
const readBalances = deps.balances ?? rpcBalances(config.rpcUrl);
|
|
26
|
-
const trade = { api, config, signer, balances: readBalances };
|
|
28
|
+
const trade = { api, config, signer, balances: readBalances, rpc: deps.rpc ?? rpcFromConnection(new Connection(config.rpcUrl, 'confirmed')), ops: deps.ops ?? new FileOpsStore(config.stateDir) };
|
|
27
29
|
const server = new McpServer({ name: 'potswap', version: VERSION });
|
|
28
30
|
const walletOr = (w) => w ?? signer?.publicKey ?? null;
|
|
29
31
|
server.registerTool('search_tokens', {
|
|
@@ -70,12 +72,12 @@ export function createServer(deps = {}) {
|
|
|
70
72
|
});
|
|
71
73
|
server.registerTool('get_quote', {
|
|
72
74
|
title: 'Get a swap quote',
|
|
73
|
-
description: 'Best route across Metis, JupiterZ, DFlow and OKX. Amount is in UI units of the input token (1 = 1 SOL). Includes the Potswap fee (returned to the wallet as POT points).',
|
|
75
|
+
description: 'Best route across Metis, JupiterZ, DFlow and OKX, plus `direct` when a Raydium CPMM pool exists (same Potswap fee, compared net). Amount is in UI units of the input token (1 = 1 SOL). Includes the Potswap fee (returned to the wallet as POT points).',
|
|
74
76
|
inputSchema: quoteShape,
|
|
75
77
|
}, async (a) => {
|
|
76
78
|
try {
|
|
77
|
-
const q = await buildQuote(api, a);
|
|
78
|
-
return ok({ ...q }, `${a.amount} ${q.inputSymbol} → ${q.outAmount} ${q.outputSymbol} via ${q.router} (fee ${q.feeLabel ?? `${q.feeBps} bps`}, impact ${q.priceImpactPct}%)`);
|
|
79
|
+
const q = await buildQuote(api, a, { direct: trade.rpc });
|
|
80
|
+
return ok({ ...q }, `${a.amount} ${q.inputSymbol} → ${q.outAmount} ${q.outputSymbol} via ${q.router} (fee ${q.feeLabel ?? `${q.feeBps} bps`}, impact ${q.priceImpactPct}%)${q.direct ? `\nDirect Raydium CPMM: ${q.direct.outAmount} ${q.outputSymbol} (${q.direct.savedVsAggregatorPct >= 0 ? '+' : ''}${q.direct.savedVsAggregatorPct.toFixed(2)}% vs aggregator, pool fee ${q.direct.poolTradeFeeBps} bps)` : ''}`);
|
|
79
81
|
}
|
|
80
82
|
catch (e) {
|
|
81
83
|
return fail(msg(e));
|
|
@@ -83,19 +85,33 @@ export function createServer(deps = {}) {
|
|
|
83
85
|
});
|
|
84
86
|
server.registerTool('swap', {
|
|
85
87
|
title: 'Swap tokens (signs with the agent wallet)',
|
|
86
|
-
description: 'Executes a swap at the best route. Requires confirm=true; otherwise returns the quote only. Protected by POTSWAP_MAX_TRADE_SOL and
|
|
87
|
-
inputSchema: { ...quoteShape, confirm: z.boolean().default(false), maxSlippageBps: z.number().int().min(1).max(5000).optional() },
|
|
88
|
+
description: 'Executes a swap at the best route. Requires confirm=true; otherwise returns the quote only. Protected by POTSWAP_MAX_TRADE_SOL, POTSWAP_MAX_SLIPPAGE_BPS and the transaction validator. route=direct uses a Raydium CPMM pool built locally (same fee); route=auto picks the better net output. opId makes the call safe to retry (a repeat returns the stored result). Every error states whether funds were debited.',
|
|
89
|
+
inputSchema: { ...quoteShape, confirm: z.boolean().default(false), maxSlippageBps: z.number().int().min(1).max(5000).optional(), route: z.enum(['jupiter', 'direct', 'auto']).default('jupiter'), opId: z.string().min(4).max(64).optional() },
|
|
88
90
|
}, async (a) => {
|
|
89
|
-
const out = await executeSwap(trade, { inputMint: a.inputMint, outputMint: a.outputMint, amount: a.amount, slippageBps: a.slippageBps ?? a.maxSlippageBps, confirm: a.confirm });
|
|
91
|
+
const out = await executeSwap(trade, { inputMint: a.inputMint, outputMint: a.outputMint, amount: a.amount, slippageBps: a.slippageBps ?? a.maxSlippageBps, confirm: a.confirm, route: a.route, opId: a.opId });
|
|
90
92
|
switch (out.kind) {
|
|
91
93
|
case 'no-wallet': return fail(out.message);
|
|
92
94
|
case 'refused': return fail(out.message, { quote: out.quote });
|
|
93
95
|
case 'quote-only': return ok({ confirmRequired: true, quote: out.quote }, `Quote only (confirm=true to execute): ${a.amount} ${out.quote.inputSymbol} → ${out.quote.outAmount} ${out.quote.outputSymbol} via ${out.quote.router}`);
|
|
94
96
|
case 'dry-run': return ok({ dryRun: true, quote: out.quote }, `DRY RUN, nothing signed: ${a.amount} ${out.quote.inputSymbol} → ${out.quote.outAmount} ${out.quote.outputSymbol}`);
|
|
95
97
|
case 'failed': return fail(out.message, { signature: out.signature, explorerUrl: out.explorerUrl, quote: out.quote });
|
|
96
|
-
case 'ok': return ok({ ...out.result },
|
|
98
|
+
case 'ok': return ok({ ...out.result }, `${out.result.replayed ? 'Already done (replayed): ' : 'Swapped '}${a.amount} ${out.result.inputSymbol} → ${out.result.outAmount} ${out.result.outputSymbol} via ${out.result.router}. ${out.result.explorerUrl}`);
|
|
97
99
|
}
|
|
98
100
|
});
|
|
101
|
+
server.registerTool('get_operation', {
|
|
102
|
+
title: 'Operation record',
|
|
103
|
+
description: 'State of an idempotent swap by opId: pending, sent, ok, failed or unknown, with the signature and result when known. Lists recent operations without an id.',
|
|
104
|
+
inputSchema: { id: z.string().min(4).max(64).optional(), limit: z.number().int().min(1).max(100).default(20) },
|
|
105
|
+
}, async ({ id, limit }) => {
|
|
106
|
+
if (!trade.ops)
|
|
107
|
+
return fail('No operation store configured.');
|
|
108
|
+
if (id) {
|
|
109
|
+
const r = trade.ops.get(id);
|
|
110
|
+
return r ? ok({ ...r }, `${r.id}: ${r.state}${r.signature ? ` · ${r.signature}` : ''}${r.error ? ` · ${r.error}` : ''}`) : fail(`No operation ${id}.`);
|
|
111
|
+
}
|
|
112
|
+
const rows = trade.ops.list(limit);
|
|
113
|
+
return ok({ operations: rows }, rows.map((r) => `${r.updatedAt} ${r.id} ${r.state}${r.signature ? ` ${r.signature.slice(0, 8)}…` : ''}`).join('\n') || 'No operations yet.');
|
|
114
|
+
});
|
|
99
115
|
server.registerTool('get_balances', {
|
|
100
116
|
title: 'Wallet balances',
|
|
101
117
|
description: 'SOL and SPL token balances with USD values. Defaults to the agent wallet.',
|
|
@@ -150,6 +166,7 @@ export function createServer(deps = {}) {
|
|
|
150
166
|
registerAgentTools(server, { trade, config, rpc: deps.rpc, txRpc: deps.txRpc, schedulerActive: () => !!deps.scheduler?.active });
|
|
151
167
|
registerStrategyTools(server, { trade, store: deps.strategyStore, scheduler: deps.scheduler });
|
|
152
168
|
registerObservationTools(server, { trade, config, getSlot: deps.getSlot });
|
|
169
|
+
registerDefiTools(server, { trade, config });
|
|
153
170
|
return server;
|
|
154
171
|
}
|
|
155
172
|
const quoteShape = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@potswap_io/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Potswap MCP server: best-route Solana swaps, wallet, transfers, staking, DCA / rebalance / take-profit / limit strategies and POT rewards for AI agents. Non-custodial; built on @potswap_io/sdk.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
43
|
-
"@potswap_io/sdk": "^0.
|
|
43
|
+
"@potswap_io/sdk": "^0.4.0",
|
|
44
44
|
"@solana/web3.js": "^1.99.0",
|
|
45
45
|
"zod": "^4.6.7"
|
|
46
46
|
},
|