@potswap_io/mcp 0.4.0 → 0.6.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 CHANGED
@@ -78,6 +78,7 @@ Use a dedicated agent wallet with only the funds you want the agent to control.
78
78
  | `get_positions {wallet?}` | Holdings with USD value, average cost, unrealised and realised PnL (from swap history) |
79
79
  | `get_points {wallet?}` | Season 1 points, POT allocated / claimable, next unlock |
80
80
  | `get_leaderboard` | Top wallets by fee paid |
81
+ | `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`) |
81
82
  | `get_launch_status` | Launch-pool meter (SOL / 500 target, from chain), season and day, fee split, unclaimed reward balances and the public claim ladder |
82
83
  | `get_price_history {mint, timeframe, limit}` | OHLCV candles from the token's top pool (`1m`…`1d`) |
83
84
 
@@ -124,7 +125,12 @@ Each swap carries Potswap's 2.5% integrator fee via Jupiter's referral program (
124
125
 
125
126
  **Season 0 (now, before the token):** 60% of the net fee fills the **launch pool**; when it reaches 500 SOL the POT token launches on its own liquidity pool. 20% of your net fee is set aside as your **reward balance** (in SOL): after launch it buys POT for you, when you say so (`claim now` at market, or a limit claim at your price). 20% runs the project. Every day you trade in Season 0 earns a slice of the **250M POT airdrop** (25% of supply), replayed day by day after launch: fee basis `fee^1.1`, capped at 10% of the day per wallet, round trips within 10 minutes count 25%.
126
127
 
127
- **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. Details: https://www.potswap.io
128
+ **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).
129
+
130
+ ## Also available
131
+
132
+ - **`@potswap_io/sdk`** — the same engine as a typed library for bots, scripts and other agent frameworks. The MCP server is built on it.
133
+ - **`@potswap_io/cli`** — the `potswap` command: `npx -y @potswap_io/cli quote SOL USDC 0.1`; swaps, transfers, wallet, points, launch meter, strategy management and `potswap daemon`.
128
134
 
129
135
  ## Development
130
136
 
@@ -1,8 +1,8 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { Connection } from '@solana/web3.js';
3
- import { type Config } from './config.js';
4
- import { type TradeContext } from './trade.js';
5
- import { type Rpc } from './transfer.js';
3
+ import { type Config } from '@potswap_io/sdk';
4
+ import { type TradeContext } from '@potswap_io/sdk';
5
+ import { type Rpc } from '@potswap_io/sdk';
6
6
  /** Transaction-level RPC reads; injectable for tests. */
7
7
  export interface TxRpc {
8
8
  getSignatureStatus(sig: string): Promise<{
@@ -1,12 +1,12 @@
1
1
  import { Connection } from '@solana/web3.js';
2
2
  import { z } from 'zod';
3
- import { JITOSOL_MINT, MSOL_MINT, NO_WALLET, SOL_MINT } from './config.js';
4
- import { redact, redactValue } from './redact.js';
5
- import { createWallet } from './wallet.js';
6
- import { executeSwap } from './trade.js';
7
- import { executeTransfer, rpcFromConnection } from './transfer.js';
8
- import { mapSignatureStatus, normalizeHistory } from './history.js';
9
- import { computePositions } from './pnl.js';
3
+ import { JITOSOL_MINT, MSOL_MINT, NO_WALLET, SOL_MINT } from '@potswap_io/sdk';
4
+ import { redact, redactValue } from '@potswap_io/sdk';
5
+ import { createWallet } from '@potswap_io/sdk';
6
+ import { executeSwap } from '@potswap_io/sdk';
7
+ import { executeTransfer, rpcFromConnection } from '@potswap_io/sdk';
8
+ import { mapSignatureStatus, normalizeHistory } from '@potswap_io/sdk';
9
+ import { computePositions } from '@potswap_io/sdk';
10
10
  const ok = (data, summary) => ({ content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data) });
11
11
  const fail = (message, extra = {}) => ({ content: [{ type: 'text', text: redact(message) }], structuredContent: redactValue({ error: message, ...extra }), isError: true });
12
12
  const MINT = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/);
package/dist/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  // Potswap MCP server over stdio, or `--daemon` to run strategies headlessly (PRD P11.11).
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { createServer, VERSION } from './server.js';
5
- import { loadConfig } from './config.js';
6
- import { log } from './redact.js';
7
- import { createRuntime } from './runtime.js';
5
+ import { loadConfig } from '@potswap_io/sdk';
6
+ import { log } from '@potswap_io/sdk';
7
+ import { createRuntime } from '@potswap_io/sdk';
8
8
  const config = loadConfig();
9
9
  const daemon = process.argv.includes('--daemon');
10
10
  const rt = createRuntime(config);
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type Config, type TradeContext } from '@potswap_io/sdk';
3
+ export interface ObservationToolDeps {
4
+ trade: TradeContext;
5
+ config: Config;
6
+ getSlot?: () => Promise<number>;
7
+ }
8
+ export declare function registerObservationTools(server: McpServer, deps: ObservationToolDeps): void;
@@ -0,0 +1,72 @@
1
+ import { Connection } from '@solana/web3.js';
2
+ import { z } from 'zod';
3
+ import { NO_WALLET, OBSERVATION_KINDS, aggregate, redact, redactValue, signConsumption, signObservation, verifyObservation } from '@potswap_io/sdk';
4
+ const ok = (data, summary) => ({ content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data) });
5
+ const fail = (message, extra = {}) => ({ content: [{ type: 'text', text: redact(message) }], structuredContent: redactValue({ error: message, ...extra }), isError: true });
6
+ const MINT = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/);
7
+ const KIND = z.enum(OBSERVATION_KINDS);
8
+ export function registerObservationTools(server, deps) {
9
+ const { trade, config } = deps;
10
+ const api = trade.api;
11
+ const getSlot = deps.getSlot ?? (() => new Connection(config.rpcUrl, 'confirmed').getSlot());
12
+ server.registerTool('observe_publish', {
13
+ title: 'Publish a signed observation',
14
+ description: 'Signs a market observation (price, liquidity, volume24h, holders, risk, route) with the agent wallet, anchored to the current slot, and posts it to the open Potswap index. Free; no funds move. Other agents can verify and consume it; verified consumption earns the publisher Season 2 rewards.',
15
+ inputSchema: { kind: KIND, mint: MINT, value: z.number().finite(), unit: z.string().min(1).max(16).optional(), source: z.string().min(1).max(64), ttlSec: z.number().int().min(10).max(86400).default(300), note: z.string().max(280).optional() },
16
+ }, async (a) => {
17
+ if (!trade.signer)
18
+ return fail(NO_WALLET);
19
+ try {
20
+ const slot = await getSlot();
21
+ const obs = signObservation(trade.signer, { ...a, slot });
22
+ const r = await api.publishObservation(obs);
23
+ return ok({ ...obs, ...r }, `Published ${a.kind} for ${a.mint.slice(0, 4)}… = ${a.value} ${obs.unit} (id ${obs.id}, slot ${slot}, ttl ${obs.ttlSec}s)${r.duplicate ? ' — already indexed' : ''}.`);
24
+ }
25
+ catch (e) {
26
+ return fail(e instanceof Error ? e.message : String(e));
27
+ }
28
+ });
29
+ server.registerTool('observe_query', {
30
+ title: 'Query observations',
31
+ description: 'Fresh observations from the open index, newest first, with a per-publisher median aggregate when mint and kind are given. Free, no wallet needed.',
32
+ inputSchema: { mint: MINT.optional(), kind: KIND.optional(), publisher: MINT.optional(), limit: z.number().int().min(1).max(200).default(50), includeStale: z.boolean().default(false) },
33
+ }, async (a) => {
34
+ try {
35
+ const r = await api.observations({ mint: a.mint, kind: a.kind, publisher: a.publisher, limit: a.limit, fresh: !a.includeStale });
36
+ const agg = a.mint && a.kind ? aggregate(r.items, a.kind, a.mint, r.now ?? Date.now()) : undefined;
37
+ return ok({ ...r, ...(agg ? { aggregate: agg } : {}) }, agg
38
+ ? `${agg.count} fresh ${a.kind} observation(s) from ${agg.publishers} publisher(s)${agg.median !== null ? ` · median ${agg.median} · spread ${agg.spreadPct?.toFixed(2)}%` : ''}`
39
+ : `${r.items.length} observation(s)` + (r.items.length ? `\n` + r.items.slice(0, 10).map((o) => `${new Date(o.observedAt).toISOString()} ${o.kind} ${o.mint.slice(0, 4)}… = ${o.value} ${o.unit} by ${o.publisher.slice(0, 4)}… (${o.source})`).join('\n') : ''));
40
+ }
41
+ catch (e) {
42
+ return fail(e instanceof Error ? e.message : String(e));
43
+ }
44
+ });
45
+ server.registerTool('observe_verify', {
46
+ title: 'Verify an observation',
47
+ description: 'Checks an observation locally: schema, id, Ed25519 signature by its publisher, freshness; for price observations also the deviation from the current Potswap price.',
48
+ inputSchema: { observation: z.record(z.string(), z.unknown()) },
49
+ }, async ({ observation }) => {
50
+ const o = observation;
51
+ let referencePrice = null;
52
+ if (o.kind === 'price' && o.mint)
53
+ referencePrice = (await api.prices([o.mint]).catch(() => ({})))[o.mint] ?? null;
54
+ const v = verifyObservation(observation, { referencePrice });
55
+ return ok({ ...v, referencePrice }, v.ok ? `Valid${v.fresh ? ', fresh' : ', expired'}${v.deviationPct !== undefined && v.deviationPct !== null ? ` · ${v.deviationPct >= 0 ? '+' : ''}${v.deviationPct.toFixed(2)}% vs current price` : ''}.` : `Invalid: ${v.reason}`);
56
+ });
57
+ server.registerTool('observe_consume', {
58
+ title: 'Record that you used an observation',
59
+ description: 'Signs a receipt with the agent wallet saying this observation informed a decision. Receipts weight the publisher\'s Season 2 rewards. Free.',
60
+ inputSchema: { id: z.string().regex(/^[0-9a-f]{32}$/) },
61
+ }, async ({ id }) => {
62
+ if (!trade.signer)
63
+ return fail(NO_WALLET);
64
+ try {
65
+ const r = await api.consumeObservation(signConsumption(trade.signer, id));
66
+ return ok(r, `Receipt recorded for ${id} (publisher ${String(r.publisher).slice(0, 4)}…)${r.duplicate ? ' — already recorded' : ''}.`);
67
+ }
68
+ catch (e) {
69
+ return fail(e instanceof Error ? e.message : String(e));
70
+ }
71
+ });
72
+ }
package/dist/server.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { type FetchFn } from './api.js';
3
- import { SOL_MINT, USDC_MINT, type Config } from './config.js';
4
- import { type BalancesFn } from './trade.js';
5
- import { type Signer } from './wallet.js';
2
+ import { type FetchFn } from '@potswap_io/sdk';
3
+ import { SOL_MINT, USDC_MINT, type Config } from '@potswap_io/sdk';
4
+ import { type BalancesFn } from '@potswap_io/sdk';
5
+ import { type Signer } from '@potswap_io/sdk';
6
6
  import { type TxRpc } from './agentTools.js';
7
- import type { Rpc } from './transfer.js';
8
- import type { StrategyStore } from './strategies/store.js';
9
- import type { Scheduler } from './strategies/scheduler.js';
10
- export declare const VERSION = "0.4.0";
7
+ import type { Rpc } from '@potswap_io/sdk';
8
+ import type { StrategyStore } from '@potswap_io/sdk';
9
+ import type { Scheduler } from '@potswap_io/sdk';
10
+ export declare const VERSION = "0.6.0";
11
11
  export interface ServerDeps {
12
12
  config?: Config;
13
13
  signer?: Signer | null;
@@ -20,6 +20,8 @@ export interface ServerDeps {
20
20
  /** Transfer / transaction RPC surfaces; injectable for tests (P13). */
21
21
  rpc?: Rpc;
22
22
  txRpc?: TxRpc;
23
+ /** Current slot for observation anchoring; injectable for tests (P15). */
24
+ getSlot?: () => Promise<number>;
23
25
  }
24
26
  export declare function createServer(deps?: ServerDeps): McpServer;
25
27
  export { SOL_MINT, USDC_MINT };
package/dist/server.js CHANGED
@@ -2,15 +2,16 @@
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { Connection, PublicKey } from '@solana/web3.js';
4
4
  import { z } from 'zod';
5
- import { PotswapApi, ApiError } from './api.js';
6
- import { loadConfig, NO_WALLET, SOL_MINT, USDC_MINT } from './config.js';
7
- import { buildQuote, executeSwap } from './trade.js';
8
- import { redact, redactValue } from './redact.js';
9
- import { loadSigner } from './wallet.js';
10
- import { riskBadges, riskLevel } from './shared/risk.js';
5
+ import { PotswapApi, ApiError } from '@potswap_io/sdk';
6
+ import { loadConfig, NO_WALLET, SOL_MINT, USDC_MINT } from '@potswap_io/sdk';
7
+ import { buildQuote, executeSwap } from '@potswap_io/sdk';
8
+ import { redact, redactValue } from '@potswap_io/sdk';
9
+ import { loadSigner } from '@potswap_io/sdk';
10
+ import { riskBadges, riskLevel } from '@potswap_io/sdk';
11
11
  import { registerStrategyTools } from './strategies/tools.js';
12
12
  import { registerAgentTools } from './agentTools.js';
13
- export const VERSION = '0.4.0';
13
+ import { registerObservationTools } from './observationTools.js';
14
+ export const VERSION = '0.6.0';
14
15
  const ok = (data, summary) => ({
15
16
  content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data),
16
17
  });
@@ -148,6 +149,7 @@ export function createServer(deps = {}) {
148
149
  });
149
150
  registerAgentTools(server, { trade, config, rpc: deps.rpc, txRpc: deps.txRpc, schedulerActive: () => !!deps.scheduler?.active });
150
151
  registerStrategyTools(server, { trade, store: deps.strategyStore, scheduler: deps.scheduler });
152
+ registerObservationTools(server, { trade, config, getSlot: deps.getSlot });
151
153
  return server;
152
154
  }
153
155
  const quoteShape = {
@@ -1,7 +1,7 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { TradeContext } from '../trade.js';
3
- import { type StrategyStore } from './store.js';
4
- import type { Scheduler } from './scheduler.js';
2
+ import type { TradeContext } from '@potswap_io/sdk';
3
+ import { type StrategyStore } from '@potswap_io/sdk';
4
+ import type { Scheduler } from '@potswap_io/sdk';
5
5
  export interface StrategyDeps {
6
6
  trade: TradeContext;
7
7
  store?: StrategyStore;
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { NO_WALLET } from '../config.js';
3
- import { redact, redactValue } from '../redact.js';
4
- import { newId, SOL_MINT, nextRunAfter } from './engine.js';
5
- import { findStrategy, runsOf } from './store.js';
2
+ import { NO_WALLET } from '@potswap_io/sdk';
3
+ import { redact, redactValue } from '@potswap_io/sdk';
4
+ import { newId, SOL_MINT, nextRunAfter } from '@potswap_io/sdk';
5
+ import { findStrategy, runsOf } from '@potswap_io/sdk';
6
6
  const MINT = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/);
7
7
  const MAX_STRATEGIES = Number(process.env.POTSWAP_MAX_STRATEGIES) || 10;
8
8
  const ok = (data, summary) => ({ content: [{ type: 'text', text: redact(summary ?? JSON.stringify(data, null, 2)) }], structuredContent: redactValue(data) });
@@ -112,12 +112,14 @@ export function registerStrategyTools(server, deps) {
112
112
  });
113
113
  server.registerTool('limit_order_create', {
114
114
  title: 'Create a limit order (price-triggered swap)',
115
- description: 'Buy or sell a token when its USD price crosses a level. Runs through the strategy scheduler (needs this host open or the daemon). Fills once at the best route with the normal fee and points, then completes.',
115
+ description: 'Buy or sell a token when its USD price crosses a level. Runs through the strategy scheduler (needs this host open or the daemon). Fills once at the best route with the normal fee and points, then completes. priceSource=observations uses the median of fresh signed observations instead of the price API.',
116
116
  inputSchema: {
117
117
  side: z.enum(['buy', 'sell']), mint: MINT, quoteMint: MINT.default(SOL_MINT),
118
118
  amount: z.number().positive().describe('Input amount in UI units: quote (SOL) amount for buys, token amount for sells'),
119
119
  triggerPriceUsd: z.number().positive(), condition: z.enum(['above', 'below']),
120
120
  expiresAt: z.string().datetime().optional(), maxSlippageBps: z.number().int().min(1).max(5000).optional(),
121
+ priceSource: z.enum(['potswap', 'observations']).default('potswap').describe('observations = median of fresh signed observations from at least minPublishers publishers (PRD P15)'),
122
+ minPublishers: z.number().int().min(1).max(50).default(2),
121
123
  confirm: z.boolean().default(false),
122
124
  },
123
125
  }, async (a) => {
@@ -126,7 +128,7 @@ export function registerStrategyTools(server, deps) {
126
128
  return g;
127
129
  if (a.mint === a.quoteMint)
128
130
  return fail('mint and quoteMint must differ. Nothing was created.');
129
- const s = { ...base('limit', a.maxSlippageBps), kind: 'limit', side: a.side, mint: a.mint, quoteMint: a.quoteMint, amount: a.amount, triggerPriceUsd: a.triggerPriceUsd, condition: a.condition, expiresAt: a.expiresAt, nextRunAt: null };
131
+ const s = { ...base('limit', a.maxSlippageBps), kind: 'limit', side: a.side, mint: a.mint, quoteMint: a.quoteMint, amount: a.amount, triggerPriceUsd: a.triggerPriceUsd, condition: a.condition, expiresAt: a.expiresAt, nextRunAt: null, ...(a.priceSource === 'observations' ? { priceSource: 'observations', minPublishers: a.minPublishers } : {}) };
130
132
  return created(s, `Limit ${a.side} created: ${a.amount} ${a.side === 'buy' ? 'quote' : 'tokens'} when price ${a.condition} $${a.triggerPriceUsd}${a.expiresAt ? ` until ${a.expiresAt}` : ''}.`);
131
133
  });
132
134
  server.registerTool('strategy_list', { title: 'List strategies', description: 'All strategies with status, next run, totals and last result.', inputSchema: {} }, async () => {
package/package.json CHANGED
@@ -1,59 +1,57 @@
1
- {
2
- "name": "@potswap_io/mcp",
3
- "version": "0.4.0",
4
- "description": "Potswap MCP server: best-route Solana swaps, DCA / rebalance / take-profit strategies for AI agents, non-custodial, earns POT.",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "potswap-mcp": "dist/index.js"
9
- },
10
- "main": "dist/server.js",
11
- "types": "dist/server.d.ts",
12
- "files": [
13
- "dist",
14
- "README.md",
15
- "LICENSE"
16
- ],
17
- "engines": {
18
- "node": ">=20"
19
- },
20
- "scripts": {
21
- "build": "tsc -p tsconfig.json",
22
- "dev": "tsx src/index.ts",
23
- "test": "vitest run",
24
- "typecheck": "tsc -p tsconfig.json --noEmit",
25
- "sync-shared": "node scripts/sync-shared.mjs",
26
- "prepublishOnly": "npm run sync-shared && npm run build"
27
- },
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://github.com/potswap-io/mcp.git"
31
- },
32
- "homepage": "https://www.potswap.io",
33
- "keywords": [
34
- "mcp",
35
- "solana",
36
- "swap",
37
- "jupiter",
38
- "ai-agent",
39
- "potswap",
40
- "model-context-protocol"
41
- ],
42
- "dependencies": {
43
- "@modelcontextprotocol/sdk": "^1.32.2",
44
- "@solana/spl-token": "^0.4.15",
45
- "@solana/web3.js": "^1.99.0",
46
- "bs58": "^6.0.0",
47
- "zod": "^4.6.7"
48
- },
49
- "devDependencies": {
50
- "@types/node": "^26.6.5",
51
- "tsx": "^4.23.15",
52
- "typescript": "^7.0.2",
53
- "vite": "^8.3.5",
54
- "vitest": "^5.0.5"
55
- },
56
- "bugs": {
57
- "url": "https://github.com/potswap-io/mcp/issues"
58
- }
59
- }
1
+ {
2
+ "name": "@potswap_io/mcp",
3
+ "version": "0.6.0",
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
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "potswap-mcp": "dist/index.js"
9
+ },
10
+ "main": "dist/server.js",
11
+ "types": "dist/server.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "dev": "tsx src/index.ts",
23
+ "test": "vitest run",
24
+ "typecheck": "tsc -p tsconfig.json --noEmit",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/potswap-io/mcp.git"
30
+ },
31
+ "homepage": "https://www.potswap.io",
32
+ "keywords": [
33
+ "mcp",
34
+ "solana",
35
+ "swap",
36
+ "jupiter",
37
+ "ai-agent",
38
+ "potswap",
39
+ "model-context-protocol"
40
+ ],
41
+ "dependencies": {
42
+ "@modelcontextprotocol/sdk": "^1.32.2",
43
+ "@potswap_io/sdk": "^0.2.0",
44
+ "@solana/web3.js": "^1.99.0",
45
+ "zod": "^4.6.7"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^26.6.5",
49
+ "tsx": "^4.23.15",
50
+ "typescript": "^7.0.2",
51
+ "vite": "^8.3.5",
52
+ "vitest": "^5.0.5"
53
+ },
54
+ "bugs": {
55
+ "url": "https://github.com/potswap-io/mcp/issues"
56
+ }
57
+ }