@potswap_io/mcp 0.7.0 → 0.8.1

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 CHANGED
@@ -80,6 +80,8 @@ Use a dedicated agent wallet with only the funds you want the agent to control.
80
80
  | `get_points {wallet?}` | Season 1 points, POT allocated / claimable, next unlock |
81
81
  | `get_leaderboard` | Top wallets by fee paid |
82
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) |
83
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 |
84
86
  | `get_price_history {mint, timeframe, limit}` | OHLCV candles from the token's top pool (`1m`…`1d`) |
85
87
 
@@ -128,6 +130,10 @@ Each swap carries Potswap's 2.5% integrator fee via Jupiter's referral program (
128
130
 
129
131
  **Seasons 1+ (30 days each):** `20M × 0.85^(n−1)` POT per season shared daily by fee basis; 30% of the net fee buys and burns POT, 20% keeps feeding reward balances, 50% team and operations. Levels (Larva → Bee → Queen, up to ×1.25) persist across seasons. `get_points` shows your balance, level and season; `get_launch_status` shows the meter. Only protocol fees enter the pool: nothing can be deposited. Full documentation: https://potswap-docs.pages.dev (every tool, configuration, limits, economy; also as /llms.txt for agents).
130
132
 
133
+ ## Owner jobs
134
+
135
+ `potswap admin sweep | claims | burn` (CLI) run the treasury split, the claims worker and the buy-and-burn with the owner's key; dry-run by default.
136
+
131
137
  ## Also available
132
138
 
133
139
  - **`@potswap_io/sdk`** — the same engine as a typed library for bots, scripts and other agent frameworks. The MCP server is built on it.
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type Config, type TradeContext } from '@potswap_io/sdk';
3
+ export declare function registerDefiTools(server: McpServer, deps: {
4
+ trade: TradeContext;
5
+ config: Config;
6
+ }): void;
@@ -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
@@ -8,7 +8,7 @@ import type { Rpc } from '@potswap_io/sdk';
8
8
  import { type OpsStore } from '@potswap_io/sdk';
9
9
  import type { StrategyStore } from '@potswap_io/sdk';
10
10
  import type { Scheduler } from '@potswap_io/sdk';
11
- export declare const VERSION = "0.7.0";
11
+ export declare const VERSION = "0.8.1";
12
12
  export interface ServerDeps {
13
13
  config?: Config;
14
14
  signer?: Signer | null;
package/dist/server.js CHANGED
@@ -11,8 +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
+ import { registerDefiTools } from './defiTools.js';
14
15
  import { FileOpsStore, rpcFromConnection } from '@potswap_io/sdk';
15
- export const VERSION = '0.7.0';
16
+ export const VERSION = '0.8.1';
16
17
  const ok = (data, summary) => ({
17
18
  content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data),
18
19
  });
@@ -165,6 +166,7 @@ export function createServer(deps = {}) {
165
166
  registerAgentTools(server, { trade, config, rpc: deps.rpc, txRpc: deps.txRpc, schedulerActive: () => !!deps.scheduler?.active });
166
167
  registerStrategyTools(server, { trade, store: deps.strategyStore, scheduler: deps.scheduler });
167
168
  registerObservationTools(server, { trade, config, getSlot: deps.getSlot });
169
+ registerDefiTools(server, { trade, config });
168
170
  return server;
169
171
  }
170
172
  const quoteShape = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@potswap_io/mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
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",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "git+https://github.com/potswap-io/mcp.git"
29
+ "url": "git+https://github.com/potswap/potswap-io.git"
30
30
  },
31
31
  "homepage": "https://www.potswap.io",
32
32
  "keywords": [
@@ -40,7 +40,7 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@modelcontextprotocol/sdk": "^1.32.2",
43
- "@potswap_io/sdk": "^0.3.0",
43
+ "@potswap_io/sdk": "^0.4.2",
44
44
  "@solana/web3.js": "^1.99.0",
45
45
  "zod": "^4.6.7"
46
46
  },
@@ -52,6 +52,6 @@
52
52
  "vitest": "^5.0.5"
53
53
  },
54
54
  "bugs": {
55
- "url": "https://github.com/potswap-io/mcp/issues"
55
+ "url": "https://github.com/potswap/potswap-io/issues"
56
56
  }
57
57
  }