@cloakely/mcp 0.8.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/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.8.0";
6
+ export declare const VERSION = "0.8.1";
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,11 +4,11 @@ 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, cloakAuctionAbi, cloakPairAbi, cloakVaultsAbi, legacyFactories, createProver, loadProver, createSharedProver, loadSharedProver, privateRouterAbi, relayerSubmitter, sharedRelayerSubmitter, sharedVaultAbi, SharedVaultClient, shieldedPoolAbi, buildClaimLink, buildRequestLink, linkAddress, linkKeys, newLinkSecret, parseClaimLink, parseRequestLink, LINK_SHARES_MAX, } from "@cloakely/sdk";
7
+ import { Cloak, CloakPrivate, cloakAuctionAbi, cloakPairAbi, cloakVaultsAbi, legacyFactories, createProver, loadProver, createSharedProver, loadSharedProver, privateRouterAbi, relayerSubmitter, sharedRelayerSubmitter, sharedVaultAbi, SharedVaultClient, shieldedPoolAbi, buildClaimLink, buildRequestLink, linkAddress, linkCheck, linkKeys, openLinkKeys, newLinkSecret, parseClaimLink, parseRequestLink, LINK_SHARES_MAX, } 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.8.0";
11
+ export const VERSION = "0.8.1";
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
 
@@ -789,7 +789,8 @@ export function createCloakServer(settings, opts = {}) {
789
789
  const l = parseClaimLink(url);
790
790
  if (l.locked && passcode === undefined)
791
791
  throw new Error(`This link is locked. Pass its passcode${l.hint ? ` (the answer to: "${l.hint}")` : ""}.`);
792
- const c = new CloakPrivate(pub, d.router, await linkKeys(l.secret, l.locked ? passcode : undefined), prover, submit, d.vaultsBlock ?? d.routerBlock, d.batcher, d.migrator);
792
+ // a locked link with a check refuses a wrong passcode here, before anything touches the network
793
+ const c = new CloakPrivate(pub, d.router, await openLinkKeys(l, passcode), prover, submit, d.vaultsBlock ?? d.routerBlock, d.batcher, d.migrator);
793
794
  for (const a of d.assets ?? [])
794
795
  c.addAsset(a);
795
796
  await c.loadMarkets();
@@ -835,7 +836,9 @@ export function createCloakServer(settings, opts = {}) {
835
836
  return { dryRun: true, wouldLock: `${fmtAmt(a, total)} in ${n} share${n > 1 ? "s" : ""} of ${fmtAmt(a, each)}`, claimFeeCovered: fmtAmt(a, claimFee * BigInt(n)), locked: !!x.passcode };
836
837
  return exclusive(async () => {
837
838
  const secret = newLinkSecret();
838
- const to = await linkAddress(await linkKeys(secret, x.passcode));
839
+ const keys = await linkKeys(secret, x.passcode);
840
+ const to = await linkAddress(keys);
841
+ const check = x.passcode ? await linkCheck(keys) : undefined;
839
842
  let block = 0n;
840
843
  const txs = [];
841
844
  for (let i = 0; i < n; i++) {
@@ -844,7 +847,7 @@ export function createCloakServer(settings, opts = {}) {
844
847
  txs.push(link(h));
845
848
  }
846
849
  spending.record(c.budget, c.value);
847
- const url = buildClaimLink({ secret, block, token: a.symbol, amount: formatUnits(n > 1 ? share : whole, a.decimals), message: x.message, from: x.from, locked: !!x.passcode, hint: x.hint, shares: n });
850
+ const url = buildClaimLink({ secret, block, token: a.symbol, amount: formatUnits(n > 1 ? share : whole, a.decimals), message: x.message, from: x.from, locked: !!x.passcode, hint: x.hint, shares: n, check });
848
851
  return {
849
852
  link: url,
850
853
  holds: `${fmtAmt(a, whole)}${n > 1 ? ` in ${n} shares of ${fmtAmt(a, share)}` : ""}`,
@@ -857,21 +860,25 @@ export function createCloakServer(settings, opts = {}) {
857
860
  server.registerTool("check_payment_link", {
858
861
  title: "Check a payment link",
859
862
  description: "What a claim link still holds (and how many shares are left), without claiming it.",
860
- inputSchema: { link: z.string().describe("The claim link (https://…/claim#k=…)"), passcode: z.string().optional() },
863
+ inputSchema: { link: z.string().describe("The claim link (https://…/claim#…)"), passcode: z.string().optional() },
861
864
  annotations: READ,
862
865
  }, safe(async ({ link: url, passcode }) => {
863
866
  const { l, c } = await linkClient(url, passcode);
864
867
  const out = {};
865
868
  let notes = 0;
869
+ let spent = 0;
866
870
  for (const sym of ["HYPE", "USDC"]) {
867
871
  const a = await linkAsset(sym).catch(() => null);
868
872
  if (!a)
869
873
  continue;
870
- const live = await c.sync(a.pool);
874
+ const all = await c.history(a.pool);
875
+ const live = all.filter((x) => !x.spent);
871
876
  notes += live.length;
877
+ spent += all.length - live.length;
872
878
  out[sym] = fmtAmt(a, live.reduce((s, x) => s + x.amount, 0n));
873
879
  }
874
- return { holds: out, ...(l.shares ? { sharesLeft: `${notes} of ${l.shares}` } : {}), ...(l.message ? { message: l.message } : {}), ...(l.from ? { from: l.from } : {}), empty: notes === 0 };
880
+ const status = notes > 0 ? (spent > 0 ? "partly claimed" : "waiting") : spent > 0 ? "claimed" : l.locked && !l.check ? "empty (a wrong passcode, already claimed, or not funded yet)" : "not funded yet";
881
+ return { holds: out, status, claimed: spent, ...(l.shares ? { sharesLeft: `${notes} of ${l.shares}` } : {}), ...(l.message ? { message: l.message } : {}), ...(l.from ? { from: l.from } : {}), empty: notes === 0 };
875
882
  }));
876
883
  server.registerTool("claim_payment_link", {
877
884
  title: "Claim a payment link",
@@ -884,13 +891,20 @@ export function createCloakServer(settings, opts = {}) {
884
891
  if (out && !isAddress(to))
885
892
  throw new Error('`to` must be "private" or a 0x address.');
886
893
  const held = [];
894
+ let spent = 0;
887
895
  for (const sym of ["HYPE", "USDC"]) {
888
896
  const a = await linkAsset(sym).catch(() => null);
889
- if (a && (await c.balance(a.pool)) > 0n)
897
+ if (!a)
898
+ continue;
899
+ const all = await c.history(a.pool);
900
+ spent += all.filter((x) => x.spent).length;
901
+ if (all.some((x) => !x.spent))
890
902
  held.push(a);
891
903
  }
892
904
  if (!held.length)
893
- throw new Error(l.locked ? "Nothing opens with that passcode, or the link was already claimed." : "This link is empty: someone already claimed it, or the sender took it back.");
905
+ throw new Error(spent > 0 ? "This link is empty: it was already claimed, or the sender took it back."
906
+ : l.locked && !l.check ? "Nothing opens with that passcode: it's wrong, the link was already claimed, or its payment hasn't landed yet."
907
+ : "This link holds nothing yet: the sender's payment hasn't landed. Try again in a minute.");
894
908
  if (isDry(dry_run))
895
909
  return { dryRun: true, holds: await Promise.all(held.map(async (a) => fmtAmt(a, await c.balance(a.pool)))), wouldClaimTo: out ? to : "this account's private balance", ...(l.shares ? { oneShareOf: l.shares } : {}) };
896
910
  return exclusive(async () => {
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.8.0",
4
+ "version": "0.8.1",
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.8.0"
50
+ "@cloakely/sdk": "^0.8.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "22.10.2",