@cloakely/mcp 0.1.2 → 0.3.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/dist/config.d.ts +5 -0
- package/dist/config.js +22 -5
- package/dist/http.js +8 -2
- package/dist/index.js +2 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +62 -20
- package/package.json +2 -2
package/dist/config.d.ts
CHANGED
|
@@ -23,3 +23,8 @@ export interface Limits {
|
|
|
23
23
|
launchesPerDay: number;
|
|
24
24
|
}
|
|
25
25
|
export declare function loadSettings(env?: NodeJS.ProcessEnv): Settings;
|
|
26
|
+
/**
|
|
27
|
+
* `settings` with the current factory, router, batcher, migrator and vaults read from CloakConfig's registry, so a
|
|
28
|
+
* router added on-chain is used without a new release. Keeps the configured deployment if the registry can't be read.
|
|
29
|
+
*/
|
|
30
|
+
export declare function withLiveDeployment(settings: Settings): Promise<Settings>;
|
package/dist/config.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { defineChain, parseEther, parseUnits } from "viem";
|
|
5
|
-
import { deploymentFor, elysiumTestnet } from "@cloakely/sdk";
|
|
4
|
+
import { createPublicClient, defineChain, http, parseEther, parseUnits } from "viem";
|
|
5
|
+
import { deploymentFor, elysiumTestnet, liveDeployment } from "@cloakely/sdk";
|
|
6
6
|
const NETWORKS = {
|
|
7
|
-
testnet: { chain: elysiumTestnet
|
|
7
|
+
testnet: { chain: elysiumTestnet },
|
|
8
8
|
};
|
|
9
9
|
export function loadSettings(env = process.env) {
|
|
10
10
|
const network = env.CLOAK_NETWORK ?? (env.CLOAK_DEPLOYMENT_FILE ? "custom" : "testnet");
|
|
@@ -23,8 +23,15 @@ export function loadSettings(env = process.env) {
|
|
|
23
23
|
const f = JSON.parse(readFileSync(env.CLOAK_DEPLOYMENT_FILE, "utf8"));
|
|
24
24
|
rpcUrl = f.rpcUrl;
|
|
25
25
|
chain = defineChain({ id: f.chainId, name: `Cloak custom (${f.chainId})`, nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 }, rpcUrls: { default: { http: [rpcUrl] } }, testnet: true });
|
|
26
|
-
deployment = { ...f, routerBlock: BigInt(f.routerBlock), assets: f.assets?.map((a) => ({ ...a, fromBlock: BigInt(a.fromBlock) })) };
|
|
27
26
|
launchesFromBlock = BigInt(f.launchesFromBlock ?? 0);
|
|
27
|
+
deployment = {
|
|
28
|
+
...f,
|
|
29
|
+
version: f.version ?? 0,
|
|
30
|
+
factoryBlock: launchesFromBlock,
|
|
31
|
+
routerBlock: BigInt(f.routerBlock),
|
|
32
|
+
vaultsBlock: f.vaultsBlock === undefined ? undefined : BigInt(f.vaultsBlock),
|
|
33
|
+
assets: f.assets?.map((a) => ({ ...a, fromBlock: BigInt(a.fromBlock) })),
|
|
34
|
+
};
|
|
28
35
|
}
|
|
29
36
|
else {
|
|
30
37
|
const n = NETWORKS[network];
|
|
@@ -32,7 +39,7 @@ export function loadSettings(env = process.env) {
|
|
|
32
39
|
throw new Error(`unknown CLOAK_NETWORK "${network}" (use testnet)`);
|
|
33
40
|
chain = n.chain;
|
|
34
41
|
deployment = deploymentFor(chain.id);
|
|
35
|
-
launchesFromBlock =
|
|
42
|
+
launchesFromBlock = deployment.factoryBlock;
|
|
36
43
|
rpcUrl = chain.rpcUrls.default.http[0];
|
|
37
44
|
}
|
|
38
45
|
if (env.CLOAK_RPC_URL)
|
|
@@ -71,3 +78,13 @@ export function loadSettings(env = process.env) {
|
|
|
71
78
|
},
|
|
72
79
|
};
|
|
73
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* `settings` with the current factory, router, batcher, migrator and vaults read from CloakConfig's registry, so a
|
|
83
|
+
* router added on-chain is used without a new release. Keeps the configured deployment if the registry can't be read.
|
|
84
|
+
*/
|
|
85
|
+
export async function withLiveDeployment(settings) {
|
|
86
|
+
const pub = createPublicClient({ chain: settings.chain, transport: http(settings.rpcUrl, { retryCount: 3, timeout: 15_000 }) });
|
|
87
|
+
const deployment = await liveDeployment(pub, settings.deployment).catch(() => settings.deployment);
|
|
88
|
+
const moved = deployment.factory.toLowerCase() !== settings.deployment.factory.toLowerCase();
|
|
89
|
+
return { ...settings, deployment, launchesFromBlock: moved ? deployment.factoryBlock : settings.launchesFromBlock };
|
|
90
|
+
}
|
package/dist/http.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
2
|
-
import { loadSettings } from "./config.js";
|
|
2
|
+
import { loadSettings, withLiveDeployment } from "./config.js";
|
|
3
3
|
import { createCloakServer } from "./server.js";
|
|
4
4
|
/**
|
|
5
5
|
* The hosted MCP endpoint as a web-standard handler (Request in, Response out), for any serverless runtime.
|
|
@@ -39,6 +39,8 @@ function limited(ip) {
|
|
|
39
39
|
return h.n > REQUESTS_PER_MINUTE ? Math.ceil((h.start + 60_000 - now) / 1000) : 0;
|
|
40
40
|
}
|
|
41
41
|
let settings;
|
|
42
|
+
let settingsAt = 0;
|
|
43
|
+
const SETTINGS_TTL = 10 * 60_000; // re-read the registry every 10 minutes
|
|
42
44
|
/** `settings` defaults to Elysium testnet, without a key (tests pass their own). */
|
|
43
45
|
export async function handleMcpRequest(req, opts = {}) {
|
|
44
46
|
if (req.method === "OPTIONS")
|
|
@@ -75,7 +77,11 @@ export async function handleMcpRequest(req, opts = {}) {
|
|
|
75
77
|
headers.delete("transfer-encoding");
|
|
76
78
|
const forward = new Request(req.url, { method: "POST", headers });
|
|
77
79
|
// never a key here, whatever the environment says
|
|
78
|
-
|
|
80
|
+
if (!opts.settings && (!settings || Date.now() - settingsAt > SETTINGS_TTL)) {
|
|
81
|
+
settingsAt = Date.now();
|
|
82
|
+
settings = withLiveDeployment(loadSettings({ CLOAK_NETWORK: "testnet", CLOAK_RPC_URL: process.env.CLOAK_RPC_URL, CLOAK_RELAYER_URL: process.env.CLOAK_RELAYER_URL }));
|
|
83
|
+
}
|
|
84
|
+
const s = opts.settings ?? (await settings);
|
|
79
85
|
const server = createCloakServer(s, { hosted: true });
|
|
80
86
|
const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true });
|
|
81
87
|
try {
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Cloak's MCP server over stdio: `npx @cloakely/mcp`. Configuration is environment variables only (see README).
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { createCloakServer, loadSettings, VERSION } from "./server.js";
|
|
5
|
+
import { withLiveDeployment } from "./config.js";
|
|
5
6
|
try {
|
|
6
|
-
const settings = loadSettings();
|
|
7
|
+
const settings = await withLiveDeployment(loadSettings());
|
|
7
8
|
const server = createCloakServer(settings);
|
|
8
9
|
await server.connect(new StdioServerTransport());
|
|
9
10
|
// stdout carries the protocol, so anything for humans goes to stderr
|
package/dist/server.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type Prover } from "@cloakely/sdk";
|
|
|
3
3
|
import type { Settings } from "./config.js";
|
|
4
4
|
export { loadSettings, type Settings, type Limits } from "./config.js";
|
|
5
5
|
export { Spending } from "./limits.js";
|
|
6
|
-
export declare const VERSION = "0.
|
|
6
|
+
export declare const VERSION = "0.3.0";
|
|
7
7
|
export declare const HOSTED_URL = "https://cloak.boblabs.tech/mcp";
|
|
8
8
|
/** Turn an SDK or chain error into one plain sentence an agent can act on. */
|
|
9
9
|
export declare function explain(e: unknown): string;
|
package/dist/server.js
CHANGED
|
@@ -4,15 +4,15 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createPublicClient, createWalletClient, erc20Abi, formatEther, formatUnits, http, isAddress, parseEther, parseUnits, zeroAddress, } from "viem";
|
|
6
6
|
import { privateKeyToAccount } from "viem/accounts";
|
|
7
|
-
import { Cloak, CloakPrivate, cloakPairAbi, createProver, loadProver, privateRouterAbi, relayerSubmitter, shieldedPoolAbi, } from "@cloakely/sdk";
|
|
7
|
+
import { Cloak, CloakPrivate, cloakAuctionAbi, cloakPairAbi, cloakVaultsAbi, createProver, loadProver, privateRouterAbi, relayerSubmitter, shieldedPoolAbi, } from "@cloakely/sdk";
|
|
8
8
|
import { Spending } from "./limits.js";
|
|
9
9
|
export { loadSettings } from "./config.js";
|
|
10
10
|
export { Spending } from "./limits.js";
|
|
11
|
-
export const VERSION = "0.
|
|
11
|
+
export const VERSION = "0.3.0";
|
|
12
12
|
export const HOSTED_URL = "https://cloak.boblabs.tech/mcp";
|
|
13
13
|
const INSTRUCTIONS = `Cloak: sealed-bid token launches and private trading on Kinetiq's Elysium (HYPE is the gas and base currency).
|
|
14
14
|
|
|
15
|
-
Launches: create_launch starts a sealed-bid auction. place_sealed_bid commits a bid that nobody can read until bidding closes; bids then open by themselves (the keeper reveals them from the drand beacon), so there is nothing to come back for. Everyone who wins pays one clearing price. After settlement, claim
|
|
15
|
+
Launches: create_launch starts a sealed-bid auction. place_sealed_bid commits a bid that nobody can read until bidding closes; bids then open by themselves (the keeper reveals them from the drand beacon), so there is nothing to come back for. Everyone who wins pays one clearing price. After settlement, claim puts won tokens straight into the private balance (and refunds into the wallet); the keeper opens each launch's private vault at settlement, and pushes bids nobody claimed to wallets publicly about an hour later. enable_private_trading opens a private vault for an older launch if nobody has yet.
|
|
16
16
|
|
|
17
17
|
Private balances: shield moves HYPE or USDC from the wallet into a private balance (the one public step). private_swap, batch_order, private_send and withdraw then run from that balance: each is proven on this machine and sent by a relayer, so the wallet never appears on chain. batch_order also hides trade size. withdraw lands funds at a normal address, ideally a fresh one. Amounts are in whole units ("0.5" HYPE), and send, sell and withdraw accept "max".
|
|
18
18
|
|
|
@@ -78,7 +78,12 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
78
78
|
});
|
|
79
79
|
const account = settings.privateKey ? privateKeyToAccount(settings.privateKey) : undefined;
|
|
80
80
|
const wallet = account ? createWalletClient({ chain: settings.chain, transport: http(settings.rpcUrl), account }) : undefined;
|
|
81
|
-
|
|
81
|
+
// earlier deployments' launches still list, settle and pay out
|
|
82
|
+
const cloak = new Cloak(pub, wallet, d.factory, (d.previous ?? []).map((p) => p.factory));
|
|
83
|
+
/** Where to start scanning a launch's bids: the current factory's deploy block, or the start for an older launch. */
|
|
84
|
+
const bidsFrom = async (auction) => (await pub.readContract({ address: auction, abi: [{ type: "function", name: "factory", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] }], functionName: "factory" }).catch(() => zeroAddress)).toLowerCase() === d.factory.toLowerCase()
|
|
85
|
+
? settings.launchesFromBlock
|
|
86
|
+
: 0n;
|
|
82
87
|
const spending = account ? new Spending(settings.limits, settings.stateDir, account.address) : undefined;
|
|
83
88
|
const submit = relayerSubmitter(d.relayerUrl);
|
|
84
89
|
const explorer = settings.chain.blockExplorers?.default.url;
|
|
@@ -93,8 +98,9 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
93
98
|
if (!wallet)
|
|
94
99
|
throw new Error("No wallet configured: set CLOAK_KEY_FILE (or CLOAK_PRIVATE_KEY) to use private balances.");
|
|
95
100
|
privP ??= (async () => {
|
|
96
|
-
const keys = await CloakPrivate.keysFromWallet(wallet, { chainId: settings.chain.id,
|
|
97
|
-
|
|
101
|
+
const keys = await CloakPrivate.keysFromWallet(wallet, { chainId: settings.chain.id, verify: true });
|
|
102
|
+
// notes are scanned from the permanent vaults' first block, whichever router is current
|
|
103
|
+
const p = new CloakPrivate(pub, d.router, keys, prover, submit, d.vaultsBlock ?? d.routerBlock, d.batcher, d.migrator);
|
|
98
104
|
for (const a of d.assets ?? [])
|
|
99
105
|
p.addAsset(a);
|
|
100
106
|
return p;
|
|
@@ -125,6 +131,9 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
125
131
|
symbols.set(k, await pub.readContract({ address: token, abi: erc20Abi, functionName: "symbol" }).catch(() => "?"));
|
|
126
132
|
return symbols.get(k);
|
|
127
133
|
}
|
|
134
|
+
async function decimalsOf(token) {
|
|
135
|
+
return Number(await pub.readContract({ address: token, abi: erc20Abi, functionName: "decimals" }).catch(() => 18));
|
|
136
|
+
}
|
|
128
137
|
/** Every asset with a private vault: HYPE, USDC-like assets, and every launch token with a private market. */
|
|
129
138
|
async function vaults() {
|
|
130
139
|
const c = { address: d.router, abi: privateRouterAbi };
|
|
@@ -132,14 +141,20 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
132
141
|
const out = [{ kind: "hype", symbol: "HYPE", token: d.whype, pool: d.hypePool, decimals: 18 }];
|
|
133
142
|
for (const a of d.assets ?? [])
|
|
134
143
|
out.push({ kind: "asset", symbol: a.symbol, token: a.token, pool: a.pool, decimals: a.decimals });
|
|
135
|
-
const toks = await Promise.all(Array.from({ length: Number(n)
|
|
144
|
+
const toks = await Promise.all(Array.from({ length: Number(n) }, (_, i) => pub.readContract({ ...c, functionName: "tokens", args: [BigInt(i)] })));
|
|
136
145
|
for (const token of toks) {
|
|
146
|
+
if (out.some((a) => a.token.toLowerCase() === token.toLowerCase()))
|
|
147
|
+
continue; // HYPE, or an asset already listed
|
|
137
148
|
const [pool, pair, symbol] = await Promise.all([
|
|
138
149
|
pub.readContract({ ...c, functionName: "poolOf", args: [token] }),
|
|
139
150
|
pub.readContract({ ...c, functionName: "pairOf", args: [token] }),
|
|
140
151
|
symbolOf(token),
|
|
141
152
|
]);
|
|
142
|
-
|
|
153
|
+
// a vault without a launch pair holds an existing token (USDC): an asset, not a market
|
|
154
|
+
if (pair === zeroAddress)
|
|
155
|
+
out.push({ kind: "asset", symbol, token, pool, decimals: await decimalsOf(token) });
|
|
156
|
+
else
|
|
157
|
+
out.push({ kind: "token", symbol, token, pool, pair, decimals: 18 });
|
|
143
158
|
}
|
|
144
159
|
return out;
|
|
145
160
|
}
|
|
@@ -467,36 +482,62 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
467
482
|
server.registerTool("my_bids", { title: "My bids", description: "The wallet's bids on a launch: deposit, whether each has opened, and once settled the tokens won, refund and any penalty.", inputSchema: { auction: addr }, annotations: READ }, safe(async ({ auction }) => {
|
|
468
483
|
const { account } = needWallet();
|
|
469
484
|
const s = await cloak.getAuction(auction);
|
|
470
|
-
const bids = await cloak.bidsOf(s.address, account.address,
|
|
485
|
+
const bids = await cloak.bidsOf(s.address, account.address, await bidsFrom(s.address));
|
|
471
486
|
return {
|
|
472
487
|
launch: s.tokenSymbol,
|
|
473
488
|
phase: s.phase,
|
|
474
489
|
bids: bids.map((b) => ({ id: b.id, deposit: hype(b.deposit), opened: b.revealed, claimed: b.claimed, ...(s.settled ? { tokensWon: formatEther(b.tokens), refund: hype(b.refund), penalty: hype(b.penalty) } : {}) })),
|
|
475
490
|
};
|
|
476
491
|
}));
|
|
477
|
-
server.registerTool("claim", {
|
|
492
|
+
server.registerTool("claim", {
|
|
493
|
+
title: "Claim tokens and refunds",
|
|
494
|
+
description: "After bids open, settle the launch if nobody has yet, then claim the wallet's tokens and refunds. Won tokens go straight into the private balance (privately: true, the default) when the launch supports it, so later trades can't be linked to the bid; refunds go to the wallet. Cloak's keeper pushes unclaimed bids to wallets publicly about an hour after bidding closes.",
|
|
495
|
+
inputSchema: { auction: addr, privately: z.boolean().optional().describe("Claim won tokens into the private balance (default true where supported)"), dry_run: dry },
|
|
496
|
+
annotations: WRITE,
|
|
497
|
+
}, safe(async ({ auction, privately, dry_run }) => {
|
|
478
498
|
const { account } = needWallet();
|
|
479
499
|
let s = await cloak.getAuction(auction);
|
|
480
500
|
if (s.phase === "commit" || s.phase === "reveal")
|
|
481
501
|
throw new Error(`${s.tokenSymbol} can't settle yet: bids are ${s.phase === "commit" ? "still being placed" : "still opening"} until ${iso(s.phase === "commit" ? s.commitEnd : s.revealEnd)}.`);
|
|
482
|
-
const bids = await cloak.bidsOf(s.address, account.address,
|
|
502
|
+
const bids = await cloak.bidsOf(s.address, account.address, await bidsFrom(s.address));
|
|
483
503
|
const open = bids.filter((b) => !b.claimed);
|
|
504
|
+
// private claims: launches from this deployment's factory, once their private vault is open
|
|
505
|
+
const canPrivate = async () => privately !== false && !s.failed && (await bidsFrom(s.address)) === settings.launchesFromBlock && (await privateTradingOn(s.token));
|
|
484
506
|
if (isDry(dry_run))
|
|
485
|
-
return { dryRun: true, wouldSettle: !s.settled, wouldClaim: open.map((b) => b.id) };
|
|
507
|
+
return { dryRun: true, wouldSettle: !s.settled, wouldClaim: open.map((b) => b.id), privately: s.settled ? await canPrivate() : privately !== false };
|
|
486
508
|
return exclusive(async () => {
|
|
487
509
|
const txs = [];
|
|
488
510
|
if (!s.settled) {
|
|
489
511
|
txs.push(link(await cloak.settle(s.address)));
|
|
490
512
|
s = await cloak.getAuction(s.address);
|
|
491
513
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
514
|
+
const priv8 = await canPrivate();
|
|
515
|
+
const won = [];
|
|
516
|
+
let publicWhy;
|
|
517
|
+
if (priv8) {
|
|
518
|
+
const p = await priv();
|
|
519
|
+
for (const b of open.filter((x) => x.tokens > 0n)) {
|
|
520
|
+
// a deposit limit can refuse a large claim; that bid is then claimed to the wallet instead
|
|
521
|
+
const ok = await pub
|
|
522
|
+
.simulateContract({ address: s.address, abi: cloakAuctionAbi, functionName: "claimPrivate", args: [b.id, 1n, 1n, "0x"], account: account.address })
|
|
523
|
+
.then(() => true, (e) => ((publicWhy = explain(e)), false));
|
|
524
|
+
if (!ok)
|
|
525
|
+
continue;
|
|
526
|
+
txs.push(link((await p.claimPrivately(wallet, s.address, b.id)).txHash));
|
|
527
|
+
won.push(b);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const rest = open.filter((b) => !won.includes(b));
|
|
531
|
+
if (rest.length)
|
|
532
|
+
txs.push(link(await cloak.claim(s.address, rest.map((b) => b.id))));
|
|
533
|
+
const after = await cloak.bidsOf(s.address, account.address, await bidsFrom(s.address));
|
|
495
534
|
return {
|
|
496
535
|
launch: s.tokenSymbol,
|
|
497
536
|
settled: s.settled,
|
|
498
537
|
...(s.failed ? { failed: "No demand was revealed, so every bid was refunded in full." } : { clearingPrice: `${formatEther(s.clearingPrice)} HYPE per token` }),
|
|
499
538
|
claimed: open.length ? open.map((b) => b.id) : "nothing left to claim (already paid out)",
|
|
539
|
+
...(won.length ? { claimedPrivately: won.map((b) => b.id), privateBalance: "won tokens are in the private balance (private_balance)" } : {}),
|
|
540
|
+
...(publicWhy ? { claimedToWallet: `some won tokens went to the wallet instead of the private balance: ${publicWhy}` } : {}),
|
|
500
541
|
tokensWon: formatEther(after.reduce((a, b) => a + b.tokens, 0n)),
|
|
501
542
|
refunds: hype(after.reduce((a, b) => a + b.refund, 0n)),
|
|
502
543
|
txs,
|
|
@@ -510,13 +551,14 @@ export function createCloakServer(settings, opts = {}) {
|
|
|
510
551
|
throw new Error(`${s.tokenSymbol} needs to settle successfully first (phase: ${s.phase}).`);
|
|
511
552
|
if (await privateTradingOn(s.token))
|
|
512
553
|
return { alreadyOn: true, token: s.token };
|
|
513
|
-
const
|
|
514
|
-
if (
|
|
515
|
-
throw new Error("This launch isn't from
|
|
554
|
+
const l = (await cloak.listLaunches()).find((x) => x.auction.toLowerCase() === s.address.toLowerCase());
|
|
555
|
+
if (!l)
|
|
556
|
+
throw new Error("This launch isn't from a Cloak factory, so it can't get a private vault.");
|
|
557
|
+
const vaults = d.vaults ?? (await pub.readContract({ address: d.router, abi: privateRouterAbi, functionName: "vaults" }));
|
|
516
558
|
if (isDry(dry_run))
|
|
517
|
-
return { dryRun: true, wouldEnable: s.tokenSymbol, launchIndex:
|
|
559
|
+
return { dryRun: true, wouldEnable: s.tokenSymbol, factory: l.factory, launchIndex: l.index };
|
|
518
560
|
return exclusive(async () => {
|
|
519
|
-
const h = await wallet.writeContract({ address:
|
|
561
|
+
const h = await wallet.writeContract({ address: vaults, abi: cloakVaultsAbi, functionName: "createPool", args: [l.factory, l.index] });
|
|
520
562
|
await receipt(h);
|
|
521
563
|
return { enabled: true, token: s.token, vault: await pub.readContract({ address: d.router, abi: privateRouterAbi, functionName: "poolOf", args: [s.token] }), tx: link(h) };
|
|
522
564
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloakely/mcp",
|
|
3
3
|
"mcpName": "io.github.NECOKIZZ/cloak",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Cloak's MCP server: let an AI agent launch tokens with sealed bids and trade them privately on Elysium, with spending limits, testnet by default and a local signer.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
48
48
|
"viem": "2.21.54",
|
|
49
49
|
"zod": "4.6.7",
|
|
50
|
-
"@cloakely/sdk": "^0.
|
|
50
|
+
"@cloakely/sdk": "^0.4.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "22.10.2",
|