@t2000/cli 3.1.1 → 3.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.
@@ -133876,159 +133876,6 @@ var require_lodash = __commonJS3({
133876
133876
  module.exports = camelCase;
133877
133877
  }
133878
133878
  });
133879
- var volo_exports = {};
133880
- __export2(volo_exports, {
133881
- MIN_STAKE_MIST: () => MIN_STAKE_MIST,
133882
- SUI_SYSTEM_STATE: () => SUI_SYSTEM_STATE,
133883
- VOLO_METADATA: () => VOLO_METADATA,
133884
- VOLO_PKG: () => VOLO_PKG,
133885
- VOLO_POOL: () => VOLO_POOL,
133886
- VSUI_TYPE: () => VSUI_TYPE,
133887
- addStakeVSuiToTx: () => addStakeVSuiToTx,
133888
- addUnstakeVSuiToTx: () => addUnstakeVSuiToTx,
133889
- buildStakeVSuiTx: () => buildStakeVSuiTx,
133890
- buildUnstakeVSuiTx: () => buildUnstakeVSuiTx,
133891
- getVoloStats: () => getVoloStats
133892
- });
133893
- async function getVoloStats() {
133894
- const res = await fetch(VOLO_STATS_URL, {
133895
- signal: AbortSignal.timeout(8e3)
133896
- });
133897
- if (!res.ok) {
133898
- throw new Error(`VOLO stats API error: HTTP ${res.status}`);
133899
- }
133900
- const data = await res.json();
133901
- const d = data.data ?? data;
133902
- return {
133903
- apy: d.apy ?? 0,
133904
- exchangeRate: d.exchange_rate ?? d.exchangeRate ?? 1,
133905
- tvl: d.tvl ?? 0
133906
- };
133907
- }
133908
- async function buildStakeVSuiTx(_client, address2, amountMist) {
133909
- if (amountMist < MIN_STAKE_MIST) {
133910
- throw new Error(`Minimum stake is 1 SUI (${MIN_STAKE_MIST} MIST). Got: ${amountMist}`);
133911
- }
133912
- const tx = new Transaction();
133913
- tx.setSender(address2);
133914
- const [suiCoin] = tx.splitCoins(tx.gas, [amountMist]);
133915
- const [vSuiCoin] = tx.moveCall({
133916
- target: `${VOLO_PKG}::stake_pool::stake`,
133917
- arguments: [
133918
- tx.object(VOLO_POOL),
133919
- tx.object(VOLO_METADATA),
133920
- tx.object(SUI_SYSTEM_STATE),
133921
- suiCoin
133922
- ]
133923
- });
133924
- tx.transferObjects([vSuiCoin], address2);
133925
- return tx;
133926
- }
133927
- async function buildUnstakeVSuiTx(client, address2, amountMist) {
133928
- const balResp = await client.getBalance({ owner: address2, coinType: VSUI_TYPE });
133929
- const totalBalance = BigInt(balResp.totalBalance);
133930
- if (totalBalance === 0n) {
133931
- throw new Error("No vSUI found in wallet.");
133932
- }
133933
- const tx = new Transaction();
133934
- tx.setSender(address2);
133935
- const requested = amountMist === "all" ? totalBalance : amountMist;
133936
- if (requested > totalBalance) {
133937
- throw new Error(`Insufficient vSUI: need ${requested} MIST, have ${totalBalance}`);
133938
- }
133939
- const vSuiCoin = coinWithBalance({ type: VSUI_TYPE, balance: requested })(tx);
133940
- const [suiCoin] = tx.moveCall({
133941
- target: `${VOLO_PKG}::stake_pool::unstake`,
133942
- arguments: [
133943
- tx.object(VOLO_POOL),
133944
- tx.object(VOLO_METADATA),
133945
- tx.object(SUI_SYSTEM_STATE),
133946
- vSuiCoin
133947
- ]
133948
- });
133949
- tx.transferObjects([suiCoin], address2);
133950
- return tx;
133951
- }
133952
- async function addStakeVSuiToTx(tx, client, address2, input) {
133953
- if (input.amountMist < MIN_STAKE_MIST) {
133954
- throw new Error(`Minimum stake is 1 SUI (${MIN_STAKE_MIST} MIST). Got: ${input.amountMist}`);
133955
- }
133956
- let suiCoin;
133957
- if (input.inputCoin) {
133958
- suiCoin = input.inputCoin;
133959
- } else {
133960
- const balResp = await client.getBalance({ owner: address2, coinType: SUI_TYPE2 });
133961
- const totalBalance = BigInt(balResp.totalBalance);
133962
- if (totalBalance < input.amountMist) {
133963
- throw new Error(`Insufficient SUI: need ${input.amountMist} MIST, have ${totalBalance}`);
133964
- }
133965
- suiCoin = coinWithBalance({
133966
- type: SUI_TYPE2,
133967
- balance: input.amountMist,
133968
- useGasCoin: false
133969
- })(tx);
133970
- }
133971
- const [vSuiCoin] = tx.moveCall({
133972
- target: `${VOLO_PKG}::stake_pool::stake`,
133973
- arguments: [
133974
- tx.object(VOLO_POOL),
133975
- tx.object(VOLO_METADATA),
133976
- tx.object(SUI_SYSTEM_STATE),
133977
- suiCoin
133978
- ]
133979
- });
133980
- return { coin: vSuiCoin, effectiveAmountMist: input.amountMist };
133981
- }
133982
- async function addUnstakeVSuiToTx(tx, client, address2, input) {
133983
- let vSuiCoin;
133984
- if (input.inputCoin) {
133985
- if (input.amountMist === "all") {
133986
- vSuiCoin = input.inputCoin;
133987
- } else {
133988
- [vSuiCoin] = tx.splitCoins(input.inputCoin, [input.amountMist]);
133989
- }
133990
- } else {
133991
- const balResp = await client.getBalance({ owner: address2, coinType: VSUI_TYPE });
133992
- const totalBalance = BigInt(balResp.totalBalance);
133993
- if (totalBalance === 0n) {
133994
- throw new Error("No vSUI found in wallet.");
133995
- }
133996
- const requested = input.amountMist === "all" ? totalBalance : input.amountMist;
133997
- if (requested > totalBalance) {
133998
- throw new Error(`Insufficient vSUI: need ${requested} MIST, have ${totalBalance}`);
133999
- }
134000
- vSuiCoin = coinWithBalance({ type: VSUI_TYPE, balance: requested })(tx);
134001
- }
134002
- const [suiCoin] = tx.moveCall({
134003
- target: `${VOLO_PKG}::stake_pool::unstake`,
134004
- arguments: [
134005
- tx.object(VOLO_POOL),
134006
- tx.object(VOLO_METADATA),
134007
- tx.object(SUI_SYSTEM_STATE),
134008
- vSuiCoin
134009
- ]
134010
- });
134011
- return { coin: suiCoin, effectiveAmountMist: input.amountMist };
134012
- }
134013
- var VOLO_PKG;
134014
- var VOLO_POOL;
134015
- var VOLO_METADATA;
134016
- var VSUI_TYPE;
134017
- var SUI_SYSTEM_STATE;
134018
- var MIN_STAKE_MIST;
134019
- var VOLO_STATS_URL;
134020
- var init_volo = __esm2({
134021
- "src/protocols/volo.ts"() {
134022
- init_token_registry();
134023
- VOLO_PKG = "0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20";
134024
- VOLO_POOL = "0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5";
134025
- VOLO_METADATA = "0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60";
134026
- VSUI_TYPE = "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT";
134027
- SUI_SYSTEM_STATE = "0x05";
134028
- MIN_STAKE_MIST = 1000000000n;
134029
- VOLO_STATS_URL = "https://open-api.naviprotocol.io/api/volo/stats";
134030
- }
134031
- });
134032
133879
  var coinSelection_exports = {};
134033
133880
  __export2(coinSelection_exports, {
134034
133881
  fetchAllCoins: () => fetchAllCoins,
@@ -134371,6 +134218,63 @@ var init_cetus_swap = __esm2({
134371
134218
  clientCache = /* @__PURE__ */ new Map();
134372
134219
  }
134373
134220
  });
134221
+ var swap_quote_exports = {};
134222
+ __export2(swap_quote_exports, {
134223
+ getSwapQuote: () => getSwapQuote
134224
+ });
134225
+ async function getSwapQuote(params) {
134226
+ const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
134227
+ const fromType = resolveTokenType2(params.from);
134228
+ const toType = resolveTokenType2(params.to);
134229
+ if (!fromType) {
134230
+ throw new T2000Error(
134231
+ "ASSET_NOT_SUPPORTED",
134232
+ `Unknown token: ${params.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`
134233
+ );
134234
+ }
134235
+ if (!toType) {
134236
+ throw new T2000Error(
134237
+ "ASSET_NOT_SUPPORTED",
134238
+ `Unknown token: ${params.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`
134239
+ );
134240
+ }
134241
+ const byAmountIn = params.byAmountIn ?? true;
134242
+ const fromDecimals = getDecimalsForCoinType(fromType);
134243
+ const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
134244
+ const route = await findSwapRoute2({
134245
+ walletAddress: params.walletAddress,
134246
+ from: fromType,
134247
+ to: toType,
134248
+ amount: rawAmount,
134249
+ byAmountIn,
134250
+ providers: params.providers
134251
+ });
134252
+ if (!route) throw new T2000Error("SWAP_FAILED", `No swap route found for ${params.from} -> ${params.to}.`);
134253
+ if (route.insufficientLiquidity) {
134254
+ throw new T2000Error("SWAP_FAILED", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
134255
+ }
134256
+ const toDecimals = getDecimalsForCoinType(toType);
134257
+ const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
134258
+ const toAmount = Number(route.amountOut) / 10 ** toDecimals;
134259
+ const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
134260
+ const { serializeCetusRoute: serializeCetusRoute2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
134261
+ const serializedRoute = serializeCetusRoute2(route, { fromCoinType: fromType, toCoinType: toType });
134262
+ return {
134263
+ fromToken: params.from,
134264
+ toToken: params.to,
134265
+ fromAmount,
134266
+ toAmount,
134267
+ priceImpact: route.priceImpact,
134268
+ route: routeDesc,
134269
+ serializedRoute
134270
+ };
134271
+ }
134272
+ var init_swap_quote = __esm2({
134273
+ "src/swap-quote.ts"() {
134274
+ init_errors9();
134275
+ init_token_registry();
134276
+ }
134277
+ });
134374
134278
  init_errors9();
134375
134279
  var MIST_PER_SUI2 = 1000000000n;
134376
134280
  var SUPPORTED_ASSETS = {
@@ -134429,7 +134333,8 @@ var SUPPORTED_ASSETS = {
134429
134333
  displayName: "XAUM"
134430
134334
  }
134431
134335
  };
134432
- var STABLE_ASSETS = ["USDC"];
134336
+ var STABLE_ASSETS = ["USDC", "USDsui"];
134337
+ var SAVEABLE_ASSETS = ["USDC", "USDsui"];
134433
134338
  var ALL_NAVI_ASSETS = Object.keys(SUPPORTED_ASSETS);
134434
134339
  var OPERATION_ASSETS = {
134435
134340
  save: ["USDC", "USDsui"],
@@ -139054,7 +138959,7 @@ var ProtocolRegistry = class {
139054
138959
  }
139055
138960
  async bestSaveRateAcrossAssets() {
139056
138961
  const candidates = [];
139057
- for (const asset of STABLE_ASSETS) {
138962
+ for (const asset of SAVEABLE_ASSETS) {
139058
138963
  for (const adapter2 of this.lending.values()) {
139059
138964
  if (!adapter2.supportedAssets.includes(asset)) continue;
139060
138965
  if (!adapter2.capabilities.includes("save")) continue;
@@ -139074,7 +138979,7 @@ var ProtocolRegistry = class {
139074
138979
  async allRatesAcrossAssets() {
139075
138980
  const results = [];
139076
138981
  const seen = /* @__PURE__ */ new Set();
139077
- for (const asset of STABLE_ASSETS) {
138982
+ for (const asset of SAVEABLE_ASSETS) {
139078
138983
  if (seen.has(asset)) continue;
139079
138984
  seen.add(asset);
139080
138985
  for (const adapter2 of this.lending.values()) {
@@ -139630,51 +139535,14 @@ var T2000 = class _T2000 extends import_index2.default {
139630
139535
  receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
139631
139536
  };
139632
139537
  }
139633
- // -- VOLO vSUI Staking --
139634
- async stakeVSui(params) {
139635
- this.enforcer.assertNotLocked();
139636
- const { buildStakeVSuiTx: buildStakeVSuiTx2, getVoloStats: getVoloStats2 } = await Promise.resolve().then(() => (init_volo(), volo_exports));
139637
- const amountMist = BigInt(Math.floor(params.amount * Number(MIST_PER_SUI2)));
139638
- const stats = await getVoloStats2();
139639
- const gasResult = await executeTx(this.client, this._signer, async () => {
139640
- return buildStakeVSuiTx2(this.client, this._address, amountMist);
139641
- });
139642
- const vSuiReceived = params.amount / stats.exchangeRate;
139643
- return {
139644
- success: true,
139645
- tx: gasResult.digest,
139646
- amountSui: params.amount,
139647
- vSuiReceived,
139648
- apy: stats.apy,
139649
- gasCost: gasResult.gasCostSui
139650
- };
139651
- }
139652
- async unstakeVSui(params) {
139653
- this.enforcer.assertNotLocked();
139654
- const { buildUnstakeVSuiTx: buildUnstakeVSuiTx2, getVoloStats: getVoloStats2, VSUI_TYPE: VSUI_TYPE2 } = await Promise.resolve().then(() => (init_volo(), volo_exports));
139655
- let amountMist;
139656
- let vSuiAmount;
139657
- if (params.amount === "all") {
139658
- amountMist = "all";
139659
- const bal = await this.client.getBalance({ owner: this._address, coinType: VSUI_TYPE2 });
139660
- vSuiAmount = Number(bal.totalBalance) / 1e9;
139661
- } else {
139662
- amountMist = BigInt(Math.floor(params.amount * 1e9));
139663
- vSuiAmount = params.amount;
139664
- }
139665
- const stats = await getVoloStats2();
139666
- const gasResult = await executeTx(this.client, this._signer, async () => {
139667
- return buildUnstakeVSuiTx2(this.client, this._address, amountMist);
139668
- });
139669
- const suiReceived = vSuiAmount * stats.exchangeRate;
139670
- return {
139671
- success: true,
139672
- tx: gasResult.digest,
139673
- vSuiAmount,
139674
- suiReceived,
139675
- gasCost: gasResult.gasCostSui
139676
- };
139677
- }
139538
+ // [S.323 / 2026-05-25] VOLO vSUI staking surfaces removed (full cut).
139539
+ // Engine cut Volo in S.277; SDK + CLI + MCP followed in S.323 because the
139540
+ // product surface (five products: Passport / Intelligence / Finance / Pay
139541
+ // / Store) doesn't include a staking primitive. vSUI still appears in the
139542
+ // codebase as a passive token (NAVI reward rewards, Cetus swap routing),
139543
+ // but there is no longer any way to MINT or REDEEM vSUI through t2000.
139544
+ // History: see spec/archive/v07e/AUDIT_V07E_EARNS_ITS_KEEP_2026-05-23.md
139545
+ // and the S.323 build-tracker entry.
139678
139546
  // -- Swap --
139679
139547
  async swap(params) {
139680
139548
  this.enforcer.assertNotLocked();
@@ -139782,36 +139650,24 @@ var T2000 = class _T2000 extends import_index2.default {
139782
139650
  gasCost: gasResult.gasCostSui
139783
139651
  };
139784
139652
  }
139653
+ /**
139654
+ * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25]
139655
+ * Thin wrapper around the standalone `getSwapQuote()`. Pre-Phase 1 this method
139656
+ * was ~50 LoC duplicating `swap-quote.ts` — missing `serializedRoute` (SPEC 20.2
139657
+ * fast-path) and the `providers` allow-list (Bug A fix / Pyth-dependent
139658
+ * provider filter for sponsored callers). Routing both API surfaces through
139659
+ * one implementation ensures fixes land for both.
139660
+ */
139785
139661
  async swapQuote(params) {
139786
- const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
139787
- const fromType = resolveTokenType2(params.from);
139788
- const toType = resolveTokenType2(params.to);
139789
- if (!fromType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.from}. Provide the full coin type.`);
139790
- if (!toType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.to}. Provide the full coin type.`);
139791
- const byAmountIn = params.byAmountIn ?? true;
139792
- const fromDecimals = getDecimalsForCoinType(fromType);
139793
- const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
139794
- const route = await findSwapRoute2({
139662
+ const { getSwapQuote: getSwapQuote2 } = await Promise.resolve().then(() => (init_swap_quote(), swap_quote_exports));
139663
+ return getSwapQuote2({
139795
139664
  walletAddress: this._address,
139796
- from: fromType,
139797
- to: toType,
139798
- amount: rawAmount,
139799
- byAmountIn
139665
+ from: params.from,
139666
+ to: params.to,
139667
+ amount: params.amount,
139668
+ byAmountIn: params.byAmountIn,
139669
+ providers: params.providers
139800
139670
  });
139801
- if (!route) throw new T2000Error("SWAP_NO_ROUTE", `No swap route found for ${params.from} -> ${params.to}.`);
139802
- if (route.insufficientLiquidity) throw new T2000Error("SWAP_NO_ROUTE", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
139803
- const toDecimals = getDecimalsForCoinType(toType);
139804
- const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
139805
- const toAmount = Number(route.amountOut) / 10 ** toDecimals;
139806
- const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
139807
- return {
139808
- fromToken: params.from,
139809
- toToken: params.to,
139810
- fromAmount,
139811
- toAmount,
139812
- priceImpact: route.priceImpact,
139813
- route: routeDesc
139814
- };
139815
139671
  }
139816
139672
  // -- Wallet --
139817
139673
  address() {
@@ -139942,6 +139798,16 @@ var T2000 = class _T2000 extends import_index2.default {
139942
139798
  ].join("\n")
139943
139799
  };
139944
139800
  }
139801
+ /**
139802
+ * [SPEC_AGENTIC_STACK P1 / SDK F2 (CLI rename support) — 2026-05-25]
139803
+ * Preferred alias of `deposit()`. The CLI surface is `t2000 fund` post-Phase 1
139804
+ * (more intuitive than "deposit" which sounds like a NAVI lending action).
139805
+ * `deposit()` stays as the canonical method name for back-compat; it is NOT
139806
+ * deprecated. This wrapper exists so SDK consumers can mirror CLI naming.
139807
+ */
139808
+ async fund() {
139809
+ return this.deposit();
139810
+ }
139945
139811
  receive(params) {
139946
139812
  const amount2 = params?.amount ?? null;
139947
139813
  const currency2 = params?.currency ?? "USDC";
@@ -140656,7 +140522,7 @@ var T2000 = class _T2000 extends import_index2.default {
140656
140522
  this.emit("yield", {
140657
140523
  earned: result.dailyEarning,
140658
140524
  total: result.totalYieldEarned,
140659
- apy: result.currentApy / 100,
140525
+ apy: result.currentApy,
140660
140526
  timestamp: Date.now()
140661
140527
  });
140662
140528
  }
@@ -140718,17 +140584,14 @@ init_errors9();
140718
140584
  init_token_registry();
140719
140585
  init_cetus_swap();
140720
140586
  init_cetus_swap();
140721
- init_volo();
140722
140587
  init_coinSelection();
140723
140588
  init_token_registry();
140724
140589
  init_errors9();
140725
140590
  init_errors9();
140726
140591
  init_errors9();
140727
- init_errors9();
140728
- init_token_registry();
140592
+ init_swap_quote();
140729
140593
  init_cetus_swap();
140730
140594
  init_token_registry();
140731
- init_volo();
140732
140595
  var SESSION_PATH = resolve$1(homedir(), ".t2000", ".session");
140733
140596
  async function resolvePin() {
140734
140597
  const envPin = process.env.T2000_PIN ?? process.env.T2000_PASSPHRASE;
@@ -141327,36 +141190,6 @@ ${text}`;
141327
141190
  }
141328
141191
  }
141329
141192
  );
141330
- server.tool(
141331
- "t2000_stake",
141332
- "Stake SUI for vSUI via VOLO liquid staking. Earn ~3-5% APY. Rewards compound automatically via exchange rate. Minimum 1 SUI.",
141333
- {
141334
- amount: external_exports.number().min(1).describe("Amount of SUI to stake (minimum 1)")
141335
- },
141336
- async ({ amount: amount2 }) => {
141337
- try {
141338
- const result = await mutex.run(() => agent.stakeVSui({ amount: amount2 }));
141339
- return { content: [{ type: "text", text: JSON.stringify(result) }] };
141340
- } catch (err) {
141341
- return errorResult(err);
141342
- }
141343
- }
141344
- );
141345
- server.tool(
141346
- "t2000_unstake",
141347
- 'Unstake vSUI back to SUI. Returns SUI including accumulated yield. Use amount in vSUI units or "all" to unstake entire position.',
141348
- {
141349
- amount: external_exports.union([external_exports.number().positive(), external_exports.literal("all")]).describe('Amount of vSUI to unstake, or "all"')
141350
- },
141351
- async ({ amount: amount2 }) => {
141352
- try {
141353
- const result = await mutex.run(() => agent.unstakeVSui({ amount: amount2 }));
141354
- return { content: [{ type: "text", text: JSON.stringify(result) }] };
141355
- } catch (err) {
141356
- return errorResult(err);
141357
- }
141358
- }
141359
- );
141360
141193
  server.tool(
141361
141194
  "t2000_contact_add",
141362
141195
  "DEPRECATED \u2014 Save a contact name \u2192 Sui address mapping to ~/.t2000/contacts.json. The local-file contact map is being sunset; the canonical name system is SuiNS (register your-name.sui at https://suins.io once and every Sui app resolves it). Use this tool only if the recipient has no SuiNS name AND you need a memorable local alias. Will be removed in the next major SDK release.",
@@ -141465,7 +141298,7 @@ init_zod();
141465
141298
  var cachedSkills = null;
141466
141299
  function getBakedSkills() {
141467
141300
  if (cachedSkills) return cachedSkills;
141468
- const raw = '[{"name":"t2000-account-report","description":"Render a complete account snapshot \u2014 wallet, savings, debt, recent activity, yield, and portfolio allocation, plus a short headline. Use when asked for a full report, account summary, \\"everything about my account\\", or \\"show me the full picture\\". Multi-tool orchestration \u2014 no single CLI command covers all six dimensions.","body":"# t2000: Account Report\\n\\n## Purpose\\nRender a complete account snapshot across six dimensions \u2014 wallet, savings,\\ndebt, recent activity, yield, portfolio allocation \u2014 followed by a 2\u20133\\nsentence headline. This is a **multi-tool orchestration**, not a single CLI\\ncommand. The right call sequence depends on the consumer:\\n\\n| Consumer | Call pattern |\\n|---|---|\\n| **MCP / Cursor / Claude Desktop** | `t2000_overview` covers wallet + savings + debt + health + earnings + rewards in one call. Add `t2000_history` (limit: 20) and `t2000_positions` if you also want activity and per-position APYs. |\\n| **CLI** | `t2000 balance --show-limits` + `t2000 positions` + `t2000 history --limit 20` |\\n| **Engine (audric/web)** | 6 parallel read tools \u2014 one per rendered card (see below). Calling fewer tools = missing cards. |\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent, each read tool renders a\\ncanvas card. **Skipping a tool = missing card.** Always emit all six\\ntool_use blocks in parallel in the same assistant turn:\\n\\n| Tool | Card | Purpose |\\n|---|---|---|\\n| `balance_check` | BALANCE CHECK | Wallet, savings, debt, total |\\n| `savings_info` | SAVINGS INFO | Per-position breakdown, supply/borrow APY, daily earnings |\\n| `health_check` | HEALTH CHECK | Health factor, supplied, borrowed, max borrow, liquidation threshold |\\n| `activity_summary` | ACTIVITY SUMMARY | Monthly tx breakdown by category |\\n| `yield_summary` | YIELD SUMMARY | Today / week / month / all-time earnings, projected yearly |\\n| `portfolio_analysis` | PORTFOLIO ANALYSIS | Allocation %, week change, insights |\\n\\nAfter all six cards render, write a **2\u20133 sentence headline** that:\\n- Leads with net worth and weekly change.\\n- Mentions health factor in one phrase.\\n- Ends with the single most actionable insight (idle USDC, debt repayment, rate gap, etc).\\n- Does **NOT** narrate the cards\' contents \u2014 they render themselves.\\n- Does **NOT** list asset percentages, APYs, or savings positions in prose.\\n\\nMax 3 sentences total.\\n\\n## CLI quick command (no canvas)\\n\\nFor terminal users who just want the numbers in their shell:\\n\\n```bash\\nt2000 balance --show-limits\\nt2000 positions\\nt2000 history --limit 20\\n```\\n\\nThese three commands cover wallet + per-position APYs + recent activity.\\nFor a one-shot machine-parseable version, add `--json` to each.\\n\\n## Notes\\n\\n- This skill orchestrates **read-only** tools \u2014 no signatures, no on-chain writes.\\n- For a workflow-shaped advisor brief on top of this snapshot (recommendations, USDC APY gap, rebalance suggestion), use the `financial-report` MCP prompt \u2014 it composes this skill plus advisor framing.\\n- If the user holds non-USDC tokens, the portfolio card surfaces them but does not flag them as \\"saveable\\" \u2014 see `t2000-save` for the USDC/USDsui save-eligibility rule."},{"name":"t2000-borrow","description":"Borrow USDC or USDsui against savings collateral. Use when asked to borrow, take a loan, get credit, leverage savings, or access funds without withdrawing from savings. A 0.05% protocol fee applies. Only accepts USDC or USDsui. Always validates projected health factor before signing \u2014 refuses if HF would drop below 1.5.","body":"# t2000: Borrow USDC or USDsui\\n\\n## Purpose\\nTake a collateralized loan using savings deposits as collateral.\\nBorrowed funds go to the available balance. A 0.05% protocol fee applies.\\nUSDsui is permitted as a strategic exception (v0.51.0+) alongside USDC \u2014\\nboth have NAVI lending pools.\\n\\n## Command\\n```bash\\nt2000 borrow <amount> [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 borrow 40 # 40 USDC (default)\\nt2000 borrow 100 --asset USDsui # 100 USDsui\\n```\\n\\n`--asset` defaults to USDC when omitted.\\n\\n## Pre-borrow safety check (always runs)\\n\\nBefore broadcasting the borrow transaction, t2000 evaluates the projected\\nhealth factor and routes the user through one of three paths:\\n\\n| Projected HF after borrow | What happens |\\n|---|---|\\n| **< 1.5** | **Refuse** \u2014 borrow blocked with `HEALTH_FACTOR_TOO_LOW`. Error includes `maxBorrow` (the largest amount that keeps HF \u2265 1.5). Suggest: repay existing debt OR add more collateral. |\\n| **1.5 \u2013 2.0** | **Warn** \u2014 surface the projected HF and require explicit user confirmation. Always state: borrow amount, projected HF, current borrow APY. Do NOT silently proceed. |\\n| **> 2.0** | **Proceed** \u2014 borrow is well-collateralized, no extra confirmation needed beyond the standard signing flow. |\\n\\nAlways state to the user: **borrow amount**, **interest rate**, and\\n**projected health factor** before signing.\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent:\\n\\n1. Call `health_check` first to get current HF and `maxBorrow`.\\n2. Compute projected HF: `(supplied \xD7 liquidationThreshold) / (borrowed + amountUsd)`.\\n3. Apply the table above \u2014 refuse / warn / proceed.\\n4. On user confirmation, emit `borrow({ amount, asset })` as the write tool_use.\\n\\nBorrows are always **single-write** \u2014 never bundle with another write in a\\nPayment Intent. The user must consciously accept the debt.\\n\\n## Fees\\n\\n- Protocol fee: 0.05% of the borrow amount\\n\\n## Output\\n\\n```\\n\u2713 Borrowed $XX.XX <asset>\\n Health Factor: X.XX\\n Borrow APY: X.XX%\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Error handling\\n\\n- `NO_COLLATERAL` \u2014 no savings deposited to borrow against. Use `t2000 save` first.\\n- `HEALTH_FACTOR_TOO_LOW` \u2014 borrow would drop HF below 1.5. Error data includes `maxBorrow`. Suggest: repay debt or add collateral.\\n- `UNSUPPORTED_ASSET` \u2014 asset is not USDC or USDsui. Other tokens cannot be borrowed (NAVI doesn\'t have pools for them).\\n\\n## Repayment symmetry (important)\\n\\n**A USDsui borrow MUST be repaid with USDsui.** A USDC borrow MUST be repaid\\nwith USDC. The SDK fetches the matching coin type per borrow asset. If the\\nuser holds only the wrong stable, tell them to swap manually first \u2014 never\\nauto-chain swap + repay. See `t2000-repay` for the repay flow.\\n\\n## What\'s NOT permitted\\n\\n- Borrowing in any asset other than USDC or USDsui (no SUI, GOLD, USDT, ETH borrows \u2014 NAVI doesn\'t have lending pools for those).\\n- Borrowing without a savings position (collateral first).\\n- Borrowing that drops HF below 1.5 (always refused; safety-critical)."},{"name":"t2000-check-balance","description":"Check the t2000 agent wallet balance on Sui. Use when asked about wallet balance, how much USDC is available, savings balance, gas reserve, or total funds. Also use before any send or borrow operation to confirm sufficient funds exist.","body":"# t2000: Check Balance\\n\\n## Purpose\\nFetch the current balance across all accounts: available USDC,\\nsavings (NAVI), gas reserve (SUI), and total value.\\n\\n## Commands\\n```bash\\nt2000 balance # human-readable summary\\nt2000 balance --show-limits # includes maxWithdraw, maxBorrow, healthFactor\\nt2000 balance --json # machine-parseable JSON (works on all commands)\\n```\\n\\n## Output (default)\\n```\\nAvailable: $150.00 (checking \u2014 spendable)\\nSavings: $2,000.00 (earning 5.10% APY)\\nGas: 0.50 SUI (~$0.50)\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\nTotal: $2,150.50\\nEarning ~$0.27/day\\n```\\n\\n## Output (--show-limits)\\nAppends to the above:\\n```\\nLimits:\\n Max withdraw: $XX.XX\\n Max borrow: $XX.XX\\n Health factor: X.XX (\u221E if no active loan)\\n```\\n\\n## Notes\\n- `gasReserve.usdEquiv` is an estimate at current SUI price; it fluctuates\\n- If balance shows $0.00 available and wallet was just created, fund it first\\n via Coinbase Onramp or a direct USDC transfer to the wallet address\\n- `--json` is a global flag that works on all t2000 commands, not just balance"},{"name":"t2000-contacts","description":"Manage contacts \u2014 save a name-to-address mapping so the user can send money by name instead of pasting raw Sui addresses. Use when asked to add, remove, or list contacts, or to look up a saved address.","body":"# t2000: Contacts\\n\\n## Purpose\\nLet users send money by name instead of raw addresses. Contacts are stored\\nlocally in `~/.t2000/contacts.json` \u2014 no blockchain lookups, no network calls.\\n\\n## Commands\\n\\n```bash\\n# List all contacts\\nt2000 contacts\\n\\n# Add or update a contact\\nt2000 contacts add <name> <address>\\n\\n# Remove a contact\\nt2000 contacts remove <name>\\n```\\n\\n## Examples\\n\\n```bash\\nt2000 contacts add Tom 0x8b3e4f2a...\\n# \u2713 Added Tom (0x8b3e...f4a2)\\n\\nt2000 contacts add Tom 0xNEWADDRESS...\\n# \u2713 Updated Tom (0xNEWA...RESS)\\n\\nt2000 contacts remove Tom\\n# \u2713 Removed Tom\\n\\nt2000 contacts\\n# Contacts\\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n# Tom 0x8b3e...f4a2\\n# Alice 0x40cd...3e62\\n```\\n\\n## Sending by name\\n\\nOnce a contact is saved, use the name directly in `t2000 send`:\\n\\n```bash\\nt2000 send 50 USDC to Tom\\n# \u2713 Sent $50.00 USDC \u2192 Tom (0x8b3e...f4a2)\\n```\\n\\n## Name rules\\n- Letters, numbers, underscores only\\n- Case-insensitive (Tom = tom = TOM)\\n- Max 32 characters\\n- Reserved names: `to`, `all`, `address`\\n- Cannot start with `0x`\\n\\n## No PIN required\\nContact commands are local file operations \u2014 no wallet access, no PIN prompt.\\n\\n## JSON mode\\nAll subcommands support `--json` for structured output:\\n\\n```bash\\nt2000 contacts --json\\nt2000 contacts add Tom 0x... --json\\nt2000 contacts remove Tom --json\\n```\\n\\n## Error handling\\n- `INVALID_CONTACT_NAME`: name violates naming rules\\n- `CONTACT_NOT_FOUND`: name not in contacts when sending\\n- `INVALID_ADDRESS`: address provided to `add` is not a valid Sui address"},{"name":"t2000-engine","description":"Use the @t2000/engine package to build conversational AI agents with financial capabilities. Use when asked to set up AISDKEngine, build custom tools, configure LLM providers, handle streaming events, or integrate with MCP servers. Powers the Audric consumer product.","body":"# t2000: Agent Engine\\n\\n## Purpose\\nBuild conversational AI agents with financial capabilities on Sui.\\n`@t2000/engine` provides `AISDKEngine`, 37 financial tools (25 read + 12 write),\\nLLM orchestration via Vercel AI SDK v6, MCP client/server integration,\\nstreaming, sessions, and cost tracking.\\n\\n> The legacy `QueryEngine` + `AnthropicProvider` were deleted in engine v2.0.0 (2026-05-17).\\n> The `LLMProvider` abstraction + `AISDKAnthropicProvider` class were retired in v3.1.0\\n> (2026-05-25). `AISDKEngine` is the only engine; it wraps Vercel AI SDK v6\'s `streamText`\\n> and accepts `anthropicApiKey` (or `modelInstance` for custom providers / gateway routing).\\n\\n## Quick Start\\n```typescript\\nimport { AISDKEngine, getDefaultTools } from \'@t2000/engine\';\\nimport { T2000 } from \'@t2000/sdk\';\\n\\nconst agent = await T2000.create({ pin: process.env.T2000_PIN });\\n\\nconst engine = new AISDKEngine({\\n anthropicApiKey: process.env.ANTHROPIC_API_KEY,\\n agent,\\n tools: getDefaultTools(),\\n});\\n\\nfor await (const event of engine.submitMessage(\'What is my balance?\')) {\\n if (event.type === \'text_delta\') process.stdout.write(event.text);\\n}\\n```\\n\\n## Building Custom Tools\\n```typescript\\nimport { z } from \'zod\';\\nimport { defineTool } from \'@t2000/engine\';\\n\\nconst myTool = defineTool({\\n name: \'my_tool\',\\n description: \'Tool description for the LLM\',\\n inputSchema: z.object({ query: z.string() }),\\n isReadOnly: true,\\n isConcurrencySafe: true,\\n permissionLevel: \'auto\',\\n async call(input, context) {\\n return { data: { result: input.query }, displayText: `Result: ${input.query}` };\\n },\\n});\\n```\\n\\n> `defineTool` is the v2 factory. The pre-v2 `buildTool` was deleted in engine\\n> `1.38.0`. Signature is the same (Zod schema, isReadOnly, permissionLevel, `call`).\\n\\n## Permission Levels\\n| Level | Behavior | Use for |\\n|-------|----------|---------|\\n| `auto` | Executes immediately | Read-only queries |\\n| `confirm` | Yields `pending_action`, client executes and resumes | Financial writes |\\n| `explicit` | Never auto-dispatched by LLM | Dangerous operations |\\n\\nUSD-aware resolution: write tools with `permissionLevel: \'confirm\'` are\\ndynamically downgraded to `auto` if `amountUsd < rule.autoBelow` and the user\'s\\n`permissionConfig` is plumbed through `ToolContext`. See\\n`packages/engine/src/permission-rules.ts` for the three presets\\n(`conservative` / `balanced` / `aggressive`) and `borrow`-always-confirms rule.\\n\\n## Event Types\\n```typescript\\nfor await (const event of engine.submitMessage(prompt)) {\\n switch (event.type) {\\n case \'stream_started\': // first event \u2014 carries engine-generated streamId (v2.2.0+, when streamCheckpointStore is wired)\\n case \'text_delta\': // LLM text chunk (markers like <proactive> and <eval_summary> pass through verbatim; host strips at render)\\n case \'thinking_delta\': // Extended-thinking chunk (always-on)\\n case \'thinking_done\': // Thinking block closed\\n case \'tool_start\': // Tool execution beginning\\n case \'tool_result\': // Tool execution complete\\n case \'pending_action\': // Write tool needs approval \u2192 client executes, then resumes. action.attemptId is a UUID v4; persist on TurnMetrics + key resume `updateMany` on it\\n case \'canvas\': // Inline HTML/React canvas artifact\\n case \'turn_complete\': // Conversation turn finished\\n case \'usage\': // Token usage report (input / output / cache reads + writes)\\n case \'error\': // Unrecoverable error\\n }\\n}\\n```\\n\\n## MCP Client (consume external MCPs)\\n```typescript\\nimport { McpClientManager, NAVI_MCP_CONFIG } from \'@t2000/engine\';\\n\\nconst mcpManager = new McpClientManager();\\nawait mcpManager.connect(NAVI_MCP_CONFIG);\\n\\n// Read tools auto-use MCP when available, SDK as fallback\\nconst engine = new AISDKEngine({\\n provider,\\n agent,\\n mcpManager,\\n walletAddress: \'0x...\',\\n tools: getDefaultTools(),\\n});\\n```\\n\\n> Internally backed by `@ai-sdk/mcp`\'s `createMCPClient` since engine `v2.1.0`\\n> (SPEC 37 v0.7a Phase 4); `McpClientManager` class name + public method\\n> signatures preserved verbatim. `McpPromptAdapter` for MCP prompts is new in `v2.1.0`.\\n\\n## MCP Server (expose tools to AI clients)\\n```typescript\\nimport { registerEngineTools, getDefaultTools } from \'@t2000/engine\';\\nimport { McpServer } from \'@modelcontextprotocol/sdk/server/mcp.js\';\\n\\nconst server = new McpServer({ name: \'audric\', version: \'0.1.0\' });\\nregisterEngineTools(server, getDefaultTools());\\n// Tools exposed as audric_balance_check, audric_save_deposit, etc.\\n```\\n\\n## SSE Streaming (web apps)\\n```typescript\\n// [v2.2.0 / SPEC 37 v0.7a Phase 5 Slice A] `engineToSSE` was deleted \u2014\\n// iterate EngineEvent raw and call serializeSSE per event. Audric chat +\\n// resume routes have used this pattern since v1.4.2 (Spec G3). Hosts that\\n// want the SPEC 21.1 routing/quoting/etc \u2192 stream_state choreography wrap\\n// with `withStreamState` directly.\\nimport { serializeSSE, withStreamState } from \'@t2000/engine\';\\n\\nfor await (const event of withStreamState(engine.submitMessage(prompt))) {\\n const wireBytes = event.type === \'error\'\\n ? serializeSSE({ type: \'error\', message: event.error.message })\\n : serializeSSE(event);\\n // Send wireBytes to client via SSE\\n}\\n// Write tools yield pending_action \u2192 client executes on-chain \u2192 POST /api/engine/resume\\n```\\n\\n## Stream Checkpoint Resume (v2.2.0+)\\n```typescript\\n// Wire a checkpoint store to enable page-reload / cold-start resume of the\\n// LIVE stream. Engine emits `stream_started` first (carries the streamId),\\n// appends every event fire-and-forget, and replays the checkpoint when the\\n// host passes the id back as `EngineConfig.resumeStreamId`.\\nimport { InMemoryStreamCheckpointStore } from \'@t2000/engine\';\\n\\nconst engine = new AISDKEngine({\\n // ...\\n streamCheckpointStore: new InMemoryStreamCheckpointStore(),\\n});\\n// In-flight tool on resume = Path B (error + re-prompt). CLI / MCP / tests\\n// use the in-memory default; multi-instance hosts (audric on Vercel) inject Upstash.\\n```\\n\\n## Built-in Tools (26 \u2014 was 31 pre-S.277)\\n\\n### Read (18, parallel, auto-approved)\\n`render_canvas`, `balance_check`, `savings_info`, `health_check`, `rates_info`,\\n`transaction_history`, `swap_quote`, `explain_tx`, `portfolio_analysis`,\\n`token_prices`, `create_payment_link`, `list_payment_links`,\\n`cancel_payment_link`, `spending_analytics`, `yield_summary`,\\n`activity_summary`, `resolve_suins`, `pending_rewards`\\n\\n### Write (8, structurally serial, confirmation required)\\n`save_deposit` (USDC + USDsui), `withdraw`, `send_transfer`,\\n`borrow` (USDC + USDsui), `repay_debt` (USDC + USDsui \u2014 same asset as borrow),\\n`claim_rewards`, `harvest_rewards`, `swap_execute`\\n\\n> **S.245 (2026-05-22):** `pay_api` (write) + `mpp_services` (read) deleted\\n> per V07E_D_QUESTION_AUDITS D-2 reframe. The legacy MPP gateway\\n> capability returns as a Commerce primitive in the upcoming Audric Store\\n> SPEC \u2014 clean-slate redesign, not a port of the legacy 3-leg apps/web flow.\\n>\\n> **S.269 (2026-05-23):** `save_contact` deleted (engine-side dead \u2014 host\\n> owns Prisma persistence). V07E_INVOICE_DEPRECATION (item 7 of S.269)\\n> deleted 3 invoice tools \u2014 `create_invoice`, `list_invoices`,\\n> `cancel_invoice` \u2014 and the `InvoiceSchema` Zod definition. Payment\\n> links absorb the invoicing use case (label/memo encode invoice\\n> context). 35 \u2192 31 tools.\\n>\\n> **S.277 (2026-05-23):** \\"Earns Its Keep\\" audit cut 5 tools + 2 dead\\n> guards (engine 2.18.0). Volo trio (`volo_stats`, `volo_stake`,\\n> `volo_unstake`) \u2014 no Audric chip / product slot for liquid staking;\\n> `harvest_rewards` routes vSUI via Cetus, not Volo. `web_search`\\n> (Brave-backed) \u2014 gateway path uses Vercel AI Gateway\'s\\n> `perplexity_search` instead. `protocol_deep_dive` (DefiLlama) \u2014\\n> `rates_info` covers the in-product safety lens; engine no longer\\n> talks to `api.llama.fi`. 2 dead guards removed (`guardCostWarning`,\\n> `guardArtifactPreview`) \u2014 both unreachable post-S.245. `explain_tx`\\n> kept but description tightened to \\"arbitrary external digest only\\".\\n> SDK + CLI + MCP retain Volo for non-Audric consumers. 31 \u2192 26 tools\\n> (18 read + 8 write), 14 \u2192 12 guards.\\n>\\n> **S.269 item 6 (2026-05-23):** `save_contact` (write) deleted as part of\\n> the template-divergence cleanup slice. Engine-side dead tool \u2014 host-side\\n> Prisma persistence with no engine-owned effect; the user surface is the\\n> audric send screen, not the LLM.\\n>\\n> **S.277 (2026-05-23):** \\"Earns Its Keep\\" audit cut 5 tools from the\\n> engine surface \u2014 `volo_stats` / `volo_stake` / `volo_unstake` (no\\n> Audric chip / product slot; SDK + CLI + MCP retain Volo for non-Audric\\n> consumers), `web_search` (Brave-backed; gateway path uses Vercel AI\\n> Gateway\'s `perplexity_search`), `protocol_deep_dive` (DefiLlama-backed;\\n> rates_info is the in-product proxy). Also dropped: 2 dead guards\\n> (`costWarning`, `artifactPreview`) + the `costAware` flag. `explain_tx`\\n> kept but description tightened to \\"arbitrary external digest only\\". Net\\n> 31 \u2192 26 engine tools. See `spec/archive/v07e/AUDIT_V07E_EARNS_ITS_KEEP_2026-05-23.md`.\\n\\n> Write serialization is structural in v2 \u2014 no in-process mutex. Confirm-tier\\n> writes yield a `pending_action` event, the host round-trips through user\\n> confirm, and the next step runs the next write. Auto-execute writes\\n> (USD-aware permission resolver, sub-threshold) inherit one-write-per-step\\n> from the LLM\'s planning + the conservative-default preset.\\n\\n## Configuration\\n```typescript\\nnew AISDKEngine({\\n anthropicApiKey: process.env.ANTHROPIC_API_KEY, // Required (or pass `modelInstance` for custom providers)\\n agent, // T2000 SDK instance\\n mcpManager, // McpClientManager for MCP-first reads\\n walletAddress, // Sui address for MCP reads\\n tools: getDefaultTools(),\\n systemPrompt, // Override default Audric prompt\\n model: \'claude-sonnet-4-5\',\\n maxTurns: 10,\\n maxTokens: 4096,\\n costTracker: { budgetLimitUsd: 1.0 },\\n streamCheckpointStore, // optional, v2.2.0+ for live-stream resume\\n resumeStreamId, // optional, replays a checkpointed stream on cold start\\n});\\n```\\n\\n## Key Imports\\n```typescript\\n// Core\\nimport { AISDKEngine, getDefaultTools } from \'@t2000/engine\';\\n// Tools (defineTool is the v2 factory; READ_TOOL_SET / WRITE_TOOL_SET / READ_TOOL_NAMES are the tool registries since v3.0.0)\\nimport { defineTool, READ_TOOL_SET, WRITE_TOOL_SET, READ_TOOL_NAMES } from \'@t2000/engine\';\\n// Streaming (`engineToSSE` was deleted in v2.2.0 \u2014 see \\"SSE Streaming\\" above)\\nimport { serializeSSE, parseSSE, withStreamState } from \'@t2000/engine\';\\n// Stream checkpoint resume (v2.2.0+)\\nimport { InMemoryStreamCheckpointStore } from \'@t2000/engine\';\\n// Sessions\\nimport { MemorySessionStore } from \'@t2000/engine\';\\n// Cost\\nimport { CostTracker } from \'@t2000/engine\';\\n// Microcompact + context budgeting\\nimport { microcompact, compactMessages, estimateTokens } from \'@t2000/engine\';\\n// Granular permissions (USD-aware resolver)\\nimport {\\n resolvePermissionTier, resolveUsdValue, toolNameToOperation,\\n DEFAULT_PERMISSION_CONFIG, PERMISSION_PRESETS,\\n} from \'@t2000/engine\';\\n// MCP\\nimport {\\n McpClientManager, McpPromptAdapter,\\n NAVI_MCP_CONFIG, buildMcpTools, registerEngineTools,\\n} from \'@t2000/engine\';\\n```"},{"name":"t2000-mcp","description":"Connect a t2000 agent bank account to Claude Desktop, Cursor, Cline, Continue, or any MCP-compatible client. Use when asked to set up MCP, paste an MCP server config, install @t2000/mcp, or troubleshoot why the MCP server \\"doesn\'t do anything\\" when run from a terminal. Provides 29 tools and 14 prompts over stdio.","body":"# t2000: MCP Server\\n\\n## Purpose\\nExpose a t2000 agent bank account (Sui wallet + DeFi positions) to any\\nMCP-compatible AI client over stdio. **29 tools, 14 prompts**, safeguard\\nenforced. No global install required \u2014 the recommended path uses `npx`\\nso the AI client always pulls the latest published version.\\n\\n## \u26A0\uFE0F The most common confusion\\n\\n**`npx @t2000/mcp` is NOT a command you run from a terminal to \\"use\\" the\\nMCP server.** It is a JSON-RPC server that listens silently on `stdin`.\\nIf you run it manually it will appear to hang \u2014 that\'s correct behavior.\\nIt is meant to be launched as a subprocess by an AI client (Claude\\nDesktop, Cursor, etc.) which speaks JSON-RPC to it over `stdin`/`stdout`.\\n\\nThe JSON snippets below go into your **AI client\'s MCP settings file**,\\nnot into a shell.\\n\\n## Setup\\n\\n### 1. Create a wallet + safeguards (one-time, in a terminal)\\n\\n```bash\\n# Install CLI long enough to bootstrap a wallet and set safety limits\\nnpx @t2000/cli init\\nnpx @t2000/cli config set maxPerTx 100\\nnpx @t2000/cli config set maxDailySend 500\\n\\n# Create a session so MCP can reuse the saved PIN\\nnpx @t2000/cli balance\\n```\\n\\nThe MCP server **refuses to start** until `maxPerTx` and `maxDailySend`\\nare configured. This is intentional.\\n\\n### 2. Add the MCP server to your AI client\\n\\nRecommended config (auto-updates on every launch, no global install):\\n\\n```json\\n{\\n \\"mcpServers\\": {\\n \\"t2000\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"-y\\", \\"@t2000/mcp@latest\\"]\\n }\\n }\\n}\\n```\\n\\nAlternative (if `@t2000/cli` is already installed globally):\\n\\n```json\\n{\\n \\"mcpServers\\": {\\n \\"t2000\\": {\\n \\"command\\": \\"t2000\\",\\n \\"args\\": [\\"mcp\\"]\\n }\\n }\\n}\\n```\\n\\n### 3. Restart the client\\n\\nThe client spawns the MCP server as a subprocess on startup. You should\\nsee `t2000_*` tools appear in the tool list.\\n\\n## Per-client config file paths\\n\\n| Client | Config file |\\n|--------|-------------|\\n| Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |\\n| Claude Desktop (Windows) | `%APPDATA%\\\\Claude\\\\claude_desktop_config.json` |\\n| Cursor | Settings \u2192 MCP \u2192 Add new MCP server (or `~/.cursor/mcp.json`) |\\n| Cline | VSCode settings \u2192 `cline.mcpServers` |\\n| Continue | `~/.continue/config.json` under `mcpServers` |\\n\\n## Verification (optional, before wiring into a client)\\n\\nConfirm the server responds to a real MCP `initialize` request:\\n\\n```bash\\nprintf \'%s\\\\n\' \\\\\\n \'{\\"jsonrpc\\":\\"2.0\\",\\"id\\":1,\\"method\\":\\"initialize\\",\\"params\\":{\\"protocolVersion\\":\\"2024-11-05\\",\\"capabilities\\":{},\\"clientInfo\\":{\\"name\\":\\"test\\",\\"version\\":\\"1.0\\"}}}\' \\\\\\n | npx -y @t2000/mcp@latest\\n```\\n\\nYou should see a JSON response containing `\\"serverInfo\\":{\\"name\\":\\"t2000\\"...}`\\nand exit. If you see that, the server is healthy and ready to be launched\\nby a client.\\n\\n## Available Tools (29)\\n\\n### Read-only (15)\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_overview` | Complete account snapshot in one call |\\n| `t2000_balance` | Current balance |\\n| `t2000_address` | Wallet address |\\n| `t2000_positions` | Lending positions |\\n| `t2000_rates` | Best interest rates per asset |\\n| `t2000_all_rates` | Per-protocol rate comparison |\\n| `t2000_health` | Health factor |\\n| `t2000_history` | Transaction history |\\n| `t2000_earnings` | Yield earnings |\\n| `t2000_fund_status` | Savings fund status |\\n| `t2000_pending_rewards` | Pending protocol rewards |\\n| `t2000_deposit_info` | Deposit instructions |\\n| `t2000_receive` | Generate payment request with address, nonce, and Payment Kit URI (`sui:pay?\u2026`) |\\n| `t2000_services` | List all MPP services and endpoints |\\n| `t2000_contacts` | List saved contacts |\\n\\n### State-changing (12)\\nAll support `dryRun: true` for previews without signing.\\n\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_send` | Send USDC |\\n| `t2000_save` | Deposit to savings |\\n| `t2000_withdraw` | Withdraw from savings |\\n| `t2000_borrow` | Borrow against collateral |\\n| `t2000_repay` | Repay debt |\\n| `t2000_claim_rewards` | Claim pending protocol rewards |\\n| `t2000_pay` | Pay for and call any MPP API service with USDC |\\n| `t2000_swap` | Execute a token swap via Cetus Aggregator |\\n| `t2000_stake` | Stake SUI for vSUI via VOLO liquid staking |\\n| `t2000_unstake` | Unstake vSUI and redeem SUI |\\n| `t2000_contact_add` | Save a contact name \u2192 address |\\n| `t2000_contact_remove` | Remove a saved contact |\\n\\n### Safety (2)\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_config` | View/set limits |\\n| `t2000_lock` | Emergency freeze |\\n\\n## Prompts (14)\\n| Prompt | Description |\\n|--------|-------------|\\n| `financial-report` | Full financial summary |\\n| `optimize-yield` | Yield optimization analysis |\\n| `send-money` | Guided send with preview |\\n| `budget-check` | Can I afford $X? |\\n| `savings-strategy` | Recommend how much to save and where |\\n| `what-if` | Scenario planning \u2014 model impact before acting |\\n| `sweep` | Route idle funds to optimal earning positions |\\n| `risk-check` | Health factor, concentration, liquidation risk |\\n| `weekly-recap` | Week in review \u2014 activity, yield |\\n| `claim-rewards` | Check and claim pending protocol rewards |\\n| `safeguards` | Review safety settings \u2014 limits, lock, PIN-protected operations |\\n| `onboarding` | New user setup \u2014 deposit, first save, explore features |\\n| `emergency` | Lock account, assess damage, recovery guidance |\\n| `optimize-all` | One-shot full optimization \u2014 sweep, compare APYs, claim rewards |\\n\\n## Troubleshooting\\n\\n| Symptom | Cause | Fix |\\n|---------|-------|-----|\\n| `npx @t2000/mcp` \\"hangs\\" with no output | Working as designed \u2014 server is waiting for JSON-RPC on stdin | Don\'t run it manually; let the AI client launch it |\\n| Server exits with `Safeguards not configured` | `maxPerTx` / `maxDailySend` not set | Run `npx @t2000/cli config set maxPerTx 100 && ... maxDailySend 500` |\\n| Client shows no `t2000_*` tools after restart | Wrong config path, or stale npx cache | Verify with the `printf | npx ...` test above; clear cache with `rm -rf ~/.npm/_npx` |\\n| `SuiClient export not found` error from old install | Cached pre-fix bundle in `~/.npm/_npx` | `rm -rf ~/.npm/_npx` then restart the client |\\n\\n## Engine MCP Adapter (Audric)\\n\\n`@t2000/engine` can also expose its financial tools as MCP tools, enabling\\nAudric to serve as an MCP server alongside `@t2000/mcp`:\\n\\n```typescript\\nimport { registerEngineTools, getDefaultTools } from \'@t2000/engine\';\\nimport { McpServer } from \'@modelcontextprotocol/sdk/server/mcp.js\';\\n\\nconst server = new McpServer({ name: \'audric\', version: \'0.1.0\' });\\nregisterEngineTools(server, getDefaultTools());\\n// Exposes: audric_balance_check, audric_save_deposit, etc.\\n```\\n\\nEngine tools use `audric_` prefix to avoid collisions with `t2000_` prefixed\\ntools from `@t2000/mcp`. The engine adapter includes permission-level metadata\\nand supports the full confirmation flow.\\n\\n## Security\\n- Safeguard gate: server refuses to start without configured limits\\n- `unlock` is CLI-only \u2014 AI cannot circumvent a locked agent\\n- `dryRun: true` previews operations before signing\\n- Local-only stdio transport \u2014 key never leaves the machine"},{"name":"t2000-pay","description":"Pay for an MPP-protected API service using the t2000 wallet. Use when asked to call an AI model, search the web, generate images, send email, buy gift cards, send physical mail, check weather, execute code, or any task that requires a paid API. Handles the full MPP 402 challenge automatically. Use t2000_services to discover all available services first.","body":"# t2000: Pay for MPP API Service\\n\\n## Status\\nActive \u2014 requires `t2000` CLI with `@suimpp/mpp` installed.\\n\\n## Purpose\\nMake a paid HTTP request to any MPP-protected endpoint. Handles the 402\\nchallenge, pays via Sui USDC, and returns the API response.\\n\\n## Service Discovery\\nBefore calling `t2000 pay`, discover available services:\\n```bash\\n# CLI\\nt2000 pay https://mpp.t2000.ai/api/services\\n\\n# MCP\\nt2000_services\\n```\\n\\nAll services are hosted at `https://mpp.t2000.ai/`.\\n\\n## Command\\n```bash\\nt2000 pay <url> [options]\\n```\\n\\n## Options\\n| Option | Description | Default |\\n|--------|-------------|---------|\\n| `--method <method>` | HTTP method (GET, POST, PUT) | POST |\\n| `--data <json>` | Request body for POST/PUT | \u2014 |\\n| `--max-price <amount>` | Max USDC per request | $1.00 |\\n| `--header <key=value>` | Additional HTTP header (repeatable) | \u2014 |\\n| `--timeout <seconds>` | Request timeout in seconds | 30 |\\n| `--dry-run` | Show what would be paid without paying | \u2014 |\\n\\n## Available Services (40 services, 88 endpoints)\\n\\n> For the live, canonical list use `t2000_services` (MCP) or GET `https://mpp.t2000.ai/api/services`.\\n> The table below is a quick reference.\\n\\n### AI Models\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenAI Chat | `/openai/v1/chat/completions` | $0.01 |\\n| OpenAI Embeddings | `/openai/v1/embeddings` | $0.005 |\\n| OpenAI Audio Transcription | `/openai/v1/audio/transcriptions` | $0.01 |\\n| OpenAI Text-to-Speech | `/openai/v1/audio/speech` | $0.02 |\\n| Anthropic | `/anthropic/v1/messages` | $0.01 |\\n| Google Gemini Flash | `/gemini/v1beta/models/gemini-2.5-flash` | $0.005 |\\n| Google Gemini Pro | `/gemini/v1beta/models/gemini-2.5-pro` | $0.01 |\\n| Google Gemini Embeddings | `/gemini/v1beta/models/embedding-001` | $0.005 |\\n| DeepSeek | `/deepseek/v1/chat/completions` | $0.005 |\\n| Groq Chat | `/groq/v1/chat/completions` | $0.005 |\\n| Groq Audio Transcription | `/groq/v1/audio/transcriptions` | $0.005 |\\n| Together AI Chat | `/together/v1/chat/completions` | $0.005 |\\n| Together AI Embeddings | `/together/v1/embeddings` | $0.005 |\\n| Perplexity | `/perplexity/v1/chat/completions` | $0.01 |\\n| Mistral Chat | `/mistral/v1/chat/completions` | $0.005 |\\n| Mistral Embeddings | `/mistral/v1/embeddings` | $0.005 |\\n| Cohere Chat | `/cohere/v1/chat` | $0.005 |\\n| Cohere Embed | `/cohere/v1/embed` | $0.005 |\\n| Cohere Rerank | `/cohere/v1/rerank` | $0.005 |\\n\\n### Media & Generation\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenAI DALL-E | `/openai/v1/images/generations` | $0.05 |\\n| Fal.ai Flux Dev | `/fal/fal-ai/flux/dev` | $0.03 |\\n| Fal.ai Flux Pro | `/fal/fal-ai/flux-pro` | $0.05 |\\n| Fal.ai Flux Realism | `/fal/fal-ai/flux-realism` | $0.05 |\\n| Fal.ai Recraft 20B | `/fal/fal-ai/recraft-20b` | $0.05 |\\n| Fal.ai Whisper | `/fal/fal-ai/whisper` | $0.01 |\\n| Together AI Images | `/together/v1/images/generations` | $0.03 |\\n| ElevenLabs TTS | `/elevenlabs/v1/text-to-speech/:voiceId` | $0.05 |\\n| ElevenLabs SFX | `/elevenlabs/v1/sound-generation` | $0.05 |\\n| Replicate (any model) | `/replicate/v1/predictions` | $0.02 |\\n| Replicate (check status) | `/replicate/v1/predictions/status` | $0.005 |\\n| Stability AI (generate) | `/stability/v1/generate` | $0.03 |\\n| Stability AI (edit) | `/stability/v1/edit` | $0.03 |\\n| AssemblyAI (transcribe) | `/assemblyai/v1/transcribe` | $0.02 |\\n| AssemblyAI (get result) | `/assemblyai/v1/result` | $0.005 |\\n\\n### Search\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Brave Web Search | `/brave/v1/web/search` | $0.005 |\\n| Brave Image Search | `/brave/v1/images/search` | $0.005 |\\n| Brave News Search | `/brave/v1/news/search` | $0.005 |\\n| Brave Video Search | `/brave/v1/videos/search` | $0.005 |\\n| Brave Summarizer | `/brave/v1/summarizer/search` | $0.01 |\\n| Exa (semantic search) | `/exa/v1/search` | $0.01 |\\n| Exa (content extract) | `/exa/v1/contents` | $0.01 |\\n| Serper (Google search) | `/serper/v1/search` | $0.005 |\\n| Serper (image search) | `/serper/v1/images` | $0.005 |\\n| SerpAPI (Google search) | `/serpapi/v1/search` | $0.01 |\\n| SerpAPI (Google Flights) | `/serpapi/v1/flights` | $0.01 |\\n| SerpAPI (locations) | `/serpapi/v1/locations` | $0.005 |\\n| NewsAPI (headlines) | `/newsapi/v1/headlines` | $0.005 |\\n| NewsAPI (article search) | `/newsapi/v1/search` | $0.005 |\\n\\n### Data\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenWeather Current | `/openweather/v1/weather` | $0.005 |\\n| OpenWeather Forecast | `/openweather/v1/forecast` | $0.005 |\\n| Google Maps Geocode | `/googlemaps/v1/geocode` | $0.01 |\\n| Google Maps Places | `/googlemaps/v1/places` | $0.01 |\\n| Google Maps Directions | `/googlemaps/v1/directions` | $0.01 |\\n| CoinGecko (price) | `/coingecko/v1/price` | $0.005 |\\n| CoinGecko (markets) | `/coingecko/v1/markets` | $0.005 |\\n| CoinGecko (trending) | `/coingecko/v1/trending` | $0.005 |\\n| Alpha Vantage (quote) | `/alphavantage/v1/quote` | $0.005 |\\n| Alpha Vantage (daily) | `/alphavantage/v1/daily` | $0.005 |\\n| Alpha Vantage (search) | `/alphavantage/v1/search` | $0.005 |\\n\\n### Web & Documents\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Firecrawl Scrape | `/firecrawl/v1/scrape` | $0.01 |\\n| Firecrawl Crawl | `/firecrawl/v1/crawl` | $0.02 |\\n| Firecrawl Map | `/firecrawl/v1/map` | $0.01 |\\n| Firecrawl Extract | `/firecrawl/v1/extract` | $0.02 |\\n| Jina Reader | `/jina/v1/read` | $0.005 |\\n| ScreenshotOne | `/screenshot/v1/capture` | $0.01 |\\n| PDFShift (HTML to PDF) | `/pdfshift/v1/convert` | $0.01 |\\n| QR Code | `/qrcode/v1/generate` | $0.005 |\\n\\n### Translation\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| DeepL (translate) | `/deepl/v1/translate` | $0.005 |\\n| Google Translate | `/translate/v1/translate` | $0.005 |\\n| Google Detect Language | `/translate/v1/detect` | $0.005 |\\n\\n### Intelligence\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Hunter.io (domain search) | `/hunter/v1/search` | $0.02 |\\n| Hunter.io (verify email) | `/hunter/v1/verify` | $0.02 |\\n| IPinfo (IP lookup) | `/ipinfo/v1/lookup` | $0.005 |\\n\\n### Tools & Compute\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Judge0 Code Exec | `/judge0/v1/submissions` | $0.005 |\\n| Judge0 Languages | `/judge0/v1/languages` | $0.005 |\\n| Resend Email | `/resend/v1/emails` | $0.005 |\\n| Resend Batch Email | `/resend/v1/emails/batch` | $0.01 |\\n\\n### Commerce\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Lob Postcards | `/lob/v1/postcards` | $1.00 |\\n| Lob Letters | `/lob/v1/letters` | $1.50 |\\n| Lob Address Verify | `/lob/v1/verify` | $0.01 |\\n| Printful (browse) | `/printful/v1/products` | $0.005 |\\n| Printful (estimate) | `/printful/v1/estimate` | $0.005 |\\n| Printful (order) | `/printful/v1/order` | dynamic |\\n\\n### Messaging\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Pushover | `/pushover/v1/push` | $0.005 |\\n\\n### Security\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| VirusTotal (URL/file scan) | `/virustotal/v1/scan` | $0.01 |\\n\\n### Finance\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| ExchangeRate (rates) | `/exchangerate/v1/rates` | $0.005 |\\n| ExchangeRate (convert) | `/exchangerate/v1/convert` | $0.005 |\\n\\n### Utility\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Short.io (URL shortener) | `/shortio/v1/shorten` | $0.005 |\\n\\n## Example Commands\\n\\n### Ask an AI model\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\"model\\":\\"gpt-4o\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"Explain quantum computing in 3 sentences\\"}]}\'\\n```\\n\\n### Search the web\\n```bash\\nt2000 pay https://mpp.t2000.ai/brave/v1/web/search \\\\\\n --data \'{\\"q\\":\\"latest Sui blockchain news\\"}\'\\n```\\n\\n### Generate an image\\n```bash\\nt2000 pay https://mpp.t2000.ai/fal/fal-ai/flux/dev \\\\\\n --data \'{\\"prompt\\":\\"a futuristic city at sunset, cyberpunk style\\"}\'\\n```\\n\\n### Check weather\\n```bash\\nt2000 pay https://mpp.t2000.ai/openweather/v1/weather \\\\\\n --data \'{\\"q\\":\\"Tokyo\\"}\'\\n```\\n\\n### Send an email\\n```bash\\nt2000 pay https://mpp.t2000.ai/resend/v1/emails \\\\\\n --data \'{\\"from\\":\\"agent@t2000.ai\\",\\"to\\":\\"user@example.com\\",\\"subject\\":\\"Hello\\",\\"text\\":\\"Sent by an AI agent\\"}\'\\n```\\n\\n### Execute code\\n```bash\\nt2000 pay https://mpp.t2000.ai/judge0/v1/submissions \\\\\\n --data \'{\\"source_code\\":\\"print(42)\\",\\"language_id\\":71}\'\\n```\\n\\n### Send physical mail\\n```bash\\n# Send a postcard\\nt2000 pay https://mpp.t2000.ai/lob/v1/postcards \\\\\\n --max-price 2 \\\\\\n --data \'{\\n \\"to\\":{\\"name\\":\\"Jane Doe\\",\\"address_line1\\":\\"123 Main St\\",\\"address_city\\":\\"San Francisco\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94105\\"},\\n \\"from\\":{\\"name\\":\\"AI Agent\\",\\"address_line1\\":\\"456 Oak Ave\\",\\"address_city\\":\\"Palo Alto\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94301\\"},\\n \\"front\\":\\"https://example.com/front.png\\",\\n \\"back\\":\\"https://example.com/back.png\\",\\n \\"use_type\\":\\"operational\\"\\n }\'\\n\\n# Send a letter\\nt2000 pay https://mpp.t2000.ai/lob/v1/letters \\\\\\n --max-price 2 \\\\\\n --data \'{\\n \\"to\\":{\\"name\\":\\"Jane Doe\\",\\"address_line1\\":\\"123 Main St\\",\\"address_city\\":\\"San Francisco\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94105\\"},\\n \\"from\\":{\\"name\\":\\"AI Agent\\",\\"address_line1\\":\\"456 Oak Ave\\",\\"address_city\\":\\"Palo Alto\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94301\\"},\\n \\"file\\":\\"https://example.com/letter.pdf\\",\\n \\"use_type\\":\\"operational\\",\\n \\"color\\":false\\n }\'\\n\\n# Verify a US address\\nt2000 pay https://mpp.t2000.ai/lob/v1/verify \\\\\\n --data \'{\\"primary_line\\":\\"123 Main St\\",\\"city\\":\\"San Francisco\\",\\"state\\":\\"CA\\",\\"zip_code\\":\\"94105\\"}\'\\n```\\n\\n### Get directions\\n```bash\\nt2000 pay https://mpp.t2000.ai/googlemaps/v1/directions \\\\\\n --data \'{\\"origin\\":\\"San Francisco, CA\\",\\"destination\\":\\"Palo Alto, CA\\"}\'\\n```\\n\\n### Get crypto prices\\n```bash\\nt2000 pay https://mpp.t2000.ai/coingecko/v1/price \\\\\\n --data \'{\\"ids\\":\\"sui,bitcoin,ethereum\\",\\"vs_currencies\\":\\"usd\\"}\'\\n```\\n\\n### Get a stock quote\\n```bash\\nt2000 pay https://mpp.t2000.ai/alphavantage/v1/quote \\\\\\n --data \'{\\"symbol\\":\\"AAPL\\"}\'\\n```\\n\\n### Get breaking news\\n```bash\\nt2000 pay https://mpp.t2000.ai/newsapi/v1/headlines \\\\\\n --data \'{\\"country\\":\\"us\\",\\"category\\":\\"technology\\"}\'\\n```\\n\\n### Translate text\\n```bash\\nt2000 pay https://mpp.t2000.ai/deepl/v1/translate \\\\\\n --data \'{\\"text\\":[\\"Hello, how are you?\\"],\\"target_lang\\":\\"ES\\"}\'\\n```\\n\\n### Semantic search\\n```bash\\nt2000 pay https://mpp.t2000.ai/exa/v1/search \\\\\\n --data \'{\\"query\\":\\"best practices for AI agent payments\\",\\"numResults\\":5}\'\\n```\\n\\n### Read a URL as markdown\\n```bash\\nt2000 pay https://mpp.t2000.ai/jina/v1/read \\\\\\n --data \'{\\"url\\":\\"https://docs.sui.io/concepts/tokenomics\\"}\'\\n```\\n\\n### Google search (structured)\\n```bash\\nt2000 pay https://mpp.t2000.ai/serper/v1/search \\\\\\n --data \'{\\"q\\":\\"Sui blockchain TVL 2026\\"}\'\\n```\\n\\n### Screenshot a webpage\\n```bash\\nt2000 pay https://mpp.t2000.ai/screenshot/v1/capture \\\\\\n --data \'{\\"url\\":\\"https://example.com\\",\\"format\\":\\"png\\",\\"viewport_width\\":\\"1280\\"}\'\\n```\\n\\n### Generate a QR code\\n```bash\\nt2000 pay https://mpp.t2000.ai/qrcode/v1/generate \\\\\\n --data \'{\\"data\\":\\"https://t2000.ai\\",\\"size\\":\\"400x400\\"}\'\\n```\\n\\n### Convert HTML to PDF\\n```bash\\nt2000 pay https://mpp.t2000.ai/pdfshift/v1/convert \\\\\\n --data \'{\\"source\\":\\"https://t2000.ai/docs\\"}\'\\n```\\n\\n### Run a Replicate model\\n```bash\\nt2000 pay https://mpp.t2000.ai/replicate/v1/predictions \\\\\\n --data \'{\\"model\\":\\"meta/llama-3-70b-instruct\\",\\"input\\":{\\"prompt\\":\\"Explain DeFi in 3 sentences\\"}}\'\\n```\\n\\n### Find emails for a domain\\n```bash\\nt2000 pay https://mpp.t2000.ai/hunter/v1/search \\\\\\n --data \'{\\"domain\\":\\"mystenlabs.com\\"}\'\\n```\\n\\n### Look up an IP address\\n```bash\\nt2000 pay https://mpp.t2000.ai/ipinfo/v1/lookup \\\\\\n --data \'{\\"ip\\":\\"8.8.8.8\\"}\'\\n```\\n\\n### Order print-on-demand merchandise\\n```bash\\nt2000 pay https://mpp.t2000.ai/printful/v1/order \\\\\\n --max-price 30 \\\\\\n --data \'{\\"recipient\\":{\\"name\\":\\"Jane Doe\\",\\"address1\\":\\"123 Main St\\",\\"city\\":\\"SF\\",\\"state_code\\":\\"CA\\",\\"country_code\\":\\"US\\",\\"zip\\":\\"94105\\"},\\"items\\":[{\\"variant_id\\":4012,\\"quantity\\":1,\\"files\\":[{\\"url\\":\\"https://example.com/design.png\\"}]}]}\'\\n```\\n\\n### Search for flights\\n```bash\\nt2000 pay https://mpp.t2000.ai/serpapi/v1/flights \\\\\\n --data \'{\\"departure_id\\":\\"LAX\\",\\"arrival_id\\":\\"NRT\\",\\"outbound_date\\":\\"2026-05-01\\",\\"type\\":\\"2\\"}\'\\n```\\n\\n### Convert currency\\n```bash\\nt2000 pay https://mpp.t2000.ai/exchangerate/v1/convert \\\\\\n --data \'{\\"from\\":\\"USD\\",\\"to\\":\\"EUR\\",\\"amount\\":100}\'\\n```\\n\\n### Scan a URL for malware\\n```bash\\nt2000 pay https://mpp.t2000.ai/virustotal/v1/scan \\\\\\n --data \'{\\"url\\":\\"https://suspicious-site.com\\"}\'\\n```\\n\\n### Shorten a URL\\n```bash\\nt2000 pay https://mpp.t2000.ai/shortio/v1/shorten \\\\\\n --data \'{\\"url\\":\\"https://example.com/very/long/url/path\\"}\'\\n```\\n\\n### Send a push notification\\n```bash\\nt2000 pay https://mpp.t2000.ai/pushover/v1/push \\\\\\n --data \'{\\"user\\":\\"USER_KEY\\",\\"message\\":\\"Your agent has a message!\\"}\'\\n```\\n\\n## Flow (automatic)\\n1. Makes initial HTTP request to the URL\\n2. If 402: reads MPP challenge for amount and terms\\n3. If price <= --max-price: pays via Sui USDC\\n4. Retries with credential header\\n5. Returns the API response body\\n\\n## Safety\\n- If requested price exceeds --max-price, payment is refused (no funds spent)\\n- Default max-price: $1.00 USDC per request\\n- For commerce (mail, merch), set --max-price higher\\n- Payment only broadcast after 402 terms are validated\\n\\n## Errors\\n- `PRICE_EXCEEDS_LIMIT`: API asking more than --max-price\\n- `INSUFFICIENT_BALANCE`: not enough available USDC\\n- `UNSUPPORTED_NETWORK`: MPP requires a network other than Sui\\n- `PAYMENT_EXPIRED`: payment challenge has expired\\n- `DUPLICATE_PAYMENT`: nonce already used on-chain\\n\\n## MCP\\nVia MCP: use `t2000_services` to discover services, then `t2000_pay` to call them."},{"name":"t2000-rebalance","description":"Rebalance the wallet to a target allocation by executing multiple swaps in one atomic Payment Intent. Use when asked to rebalance, adjust allocation, \\"shuffle my positions\\", or move from one set of holdings to another. Every leg prices against the same on-chain snapshot \u2014 no cross-leg slippage drift; user signs once.","body":"# t2000: Rebalance Portfolio\\n\\n## Purpose\\nMove from a current allocation to a target allocation by emitting all\\nthe required `swap_execute` calls **in the same assistant turn** so the\\nengine compiles them into one Payment Intent. Result: every leg of the\\nrebalance prices against the same Sui state, slippage is bounded once,\\nand the user signs once.\\n\\n## When to use\\n\\n- \\"Rebalance my portfolio to 60% USDC / 30% SUI / 10% GOLD\\"\\n- \\"Move everything to USDC\\"\\n- \\"Adjust my allocation \u2014 I want less SUI exposure\\"\\n- \\"I\'m 80% SUI, get me to 50/50 with USDC\\"\\n\\n## Flow\\n\\n### Step 1 \u2014 Current allocation\\nCall `balance_check` (engine) or `t2000_balance --json` (CLI) to get the\\ncurrent breakdown. Compute the percentage held in each asset by USD value.\\n\\n### Step 2 \u2014 Plan trades\\nFor each asset, compute the delta vs the target:\\n- Asset over-allocated \u2192 swap **out** to USDC (or another reduce-target asset)\\n- Asset under-allocated \u2192 swap **in** from USDC (or another excess-source asset)\\n\\nPresent the plan to the user **before** executing:\\n\\n```\\n\u{1F4CA} REBALANCE PLAN\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Current Target \u0394\\n USDC $400 $600 +$200\\n SUI $400 $300 \u2212$100\\n GOLD $200 $100 \u2212$100\\n\\nTrades (1 atomic Payment Intent):\\n 1. swap 0.5 SUI \u2192 ~$100 USDC\\n 2. swap 0.05 GOLD \u2192 ~$100 USDC\\n\\nEstimated slippage: 0.3% on each leg\\nProceed?\\n```\\n\\n### Step 3 \u2014 Execute (bundled)\\n\\n**Critical:** emit ALL the `swap_execute` calls as parallel `tool_use` blocks\\n**in the same assistant turn**. The engine\'s permission gate compiles them\\ninto ONE Payment Intent. The user signs once; every leg either succeeds or\\nthe whole rebalance reverts.\\n\\n**Do NOT** call them sequentially across turns \u2014 that defeats the atomicity\\nand exposes the user to price drift between legs.\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: swap_execute({ from: \\"SUI\\", to: \\"USDC\\", amount: 0.5 })\\n tool_use: swap_execute({ from: \\"GOLD\\", to: \\"USDC\\", amount: 0.05 })\\n```\\n\\n### Step 4 \u2014 Summary\\nAfter the Payment Intent settles, call `balance_check` again and show the\\nfinal allocation vs target. Highlight any drift > 1% (caused by slippage\\nor rounding) and ask if the user wants a follow-up swap to close it.\\n\\n## Error handling\\n\\n| Error | Cause | What to do |\\n|---|---|---|\\n| Intent failed \u2014 `INSUFFICIENT_BALANCE` | One of the swap legs would consume more than the wallet holds | Abort the entire intent (no swaps execute). Reduce the amount on the offending leg. |\\n| Intent failed \u2014 `SLIPPAGE_EXCEEDED` | A leg exceeded the configured slippage tolerance | Abort. Re-run with looser slippage OR smaller leg sizes. |\\n| Intent failed \u2014 any reason | Atomic Payment Intent reverts the WHOLE bundle | No funds moved. Tell the user the on-chain state is unchanged. |\\n\\n## CLI fallback (no bundling)\\n\\nThe CLI does not support Payment Intent bundling today. To rebalance from\\nthe CLI, execute swaps one at a time:\\n\\n```bash\\nt2000 swap 0.5 SUI to USDC\\nt2000 swap 0.05 GOLD to USDC\\n```\\n\\nEach swap prices against the on-chain state **at the moment of execution**,\\nwhich means small drift between legs. For larger rebalances ($1k+) prefer\\nthe agent path (which bundles into one Payment Intent).\\n\\n## Fees\\n\\nPer swap leg:\\n- Cetus protocol fee: ~0.1% of swap amount (varies by pool)\\n- Audric overlay fee: 10 bps (~0.1%)\\n\\nBundled rebalances pay the same per-leg fees \u2014 bundling reduces slippage\\nrisk, not fee cost.\\n\\n## Notes\\n\\n- This skill is **engine-first** \u2014 the bundling guarantee only exists in\\n the audric/web chat agent (or any engine consumer with Payment Intent\\n compile support).\\n- For \\"optimize my yield\\" intent (sweep idle USDC into best-APY savings,\\n claim rewards, compare USDC pools), use the `optimize-all` MCP prompt\\n instead \u2014 that\'s a different shape of workflow.\\n- Health-factor check **does not run** for swap-only rebalances (no\\n collateral position changes). For rebalances that involve withdrawing\\n from savings, see `t2000-withdraw` (the safety check runs there)."},{"name":"t2000-receive","description":"Generate a payment request to receive funds into the t2000 agent wallet. Use when asked to receive money, create a payment link, share a wallet address, or generate a QR code for receiving payment. Produces a payment request with address, Sui Payment Kit URI (sui:pay?\u2026), nonce, and optional amount/memo.","body":"# t2000: Receive Payment\\n\\n## Purpose\\nGenerate a payment request containing the agent\'s wallet address, a unique\\nnonce, and a Sui Payment Kit URI (`sui:pay?\u2026`). The sender can scan the QR or\\ncopy the address to send funds. No on-chain transaction is created \u2014 this is a\\nlocal, read-only operation.\\n\\n## Command\\n```bash\\nt2000 receive [options]\\n\\n# Examples:\\nt2000 receive # Address only\\nt2000 receive --amount 25 # Request $25 USDC\\nt2000 receive --amount 100 --memo \\"Invoice #42\\" # With memo\\nt2000 receive --amount 50 --label \\"Freelance work\\" # With label\\nt2000 receive --currency SUI --amount 10 # Request SUI\\n```\\n\\n## Options\\n| Option | Description |\\n|--------|-------------|\\n| `--amount <n>` | Amount to request (omit for open amount) |\\n| `--currency <sym>` | Currency symbol (default: USDC) |\\n| `--memo <text>` | Payment note shown to sender |\\n| `--label <text>` | Description for the payment request |\\n\\n## Output\\n```\\n\u2713 Payment Request\\n\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Address 0x8b3e...d412\\n Network Sui Mainnet\\n Nonce a1b2c3d4-e5f6-7890-abcd-ef1234567890\\n Amount $25.00 USDC\\n Memo Invoice #42\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n\\n Payment URI sui:pay?receiver=0x8b3e...&amount=25000000&...\\n\\n Share this URI or scan the QR to pay via any Sui wallet.\\n```\\n\\n## SDK Usage\\n```typescript\\nconst request = agent.receive({ amount: 25, memo: \'Invoice #42\' });\\n// Returns: { address, network, amount, currency, memo, label, nonce, qrUri, displayText }\\n```\\n\\n## MCP Tool\\nTool name: `t2000_receive` (read-only, auto-approved).\\n\\n## Notes\\n- This is a **local operation** \u2014 no transaction is created, no gas is used\\n- Uses **Sui Payment Kit** \u2014 generates `sui:pay?` URIs with nonce binding\\n- The nonce is a UUID that uniquely identifies each payment request\\n- Wallets that support Payment Kit register payment in an on-chain registry, preventing double-spend\\n- Without `--amount`, the request is open-ended (any amount accepted)\\n- Default currency is USDC; specify `--currency SUI` for native SUI"},{"name":"t2000-repay","description":"Repay outstanding debt. Use when asked to repay a loan, pay back debt, reduce outstanding balance, or clear borrows. Supports partial and full repayment. User pays with USDC.","body":"# t2000: Repay Borrow\\n\\n## Purpose\\nRepay outstanding debt in USDC. Supports specific amounts or `repay all` to clear the full\\nbalance including accrued interest.\\n\\n## Command\\n```bash\\nt2000 repay <amount>\\nt2000 repay all\\n\\n# Examples:\\nt2000 repay 20\\nt2000 repay all\\n```\\n\\n## Fees\\n- No protocol fee on repayment\\n\\n## Output\\n```\\n\u2713 Repaid $XX.XX USDC\\n Remaining Debt: $XX.XX\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Notes\\n- `repay all` calculates full outstanding principal + accrued interest\\n- Available USDC balance must cover the repayment amount"},{"name":"t2000-safeguards","description":"Configure spending limits and safety controls for t2000 agent wallets. Use when asked to set transaction limits, daily send limits, lock or unlock the agent, view safeguard settings, or protect the wallet from unauthorized spending. Required before enabling MCP server access.","body":"# t2000: Agent Safeguards\\n\\n## Purpose\\nConfigure spending limits and safety guardrails for autonomous agent\\noperation. Three controls: agent lock (kill switch), per-transaction\\nlimit, and daily send limit.\\n\\n> Safeguards are enforced on CLI and MCP. All state-changing actions\\n> require explicit confirmation before execution.\\n\\n## Commands\\n```bash\\nt2000 config show # view all safeguard settings\\nt2000 config set maxPerTx 500 # max $500 per outbound transaction\\nt2000 config set maxDailySend 1000 # max $1000 outbound per day\\nt2000 lock # freeze ALL operations immediately\\nt2000 unlock # resume operations (requires PIN)\\n```\\n\\n## Controls\\n\\n| Control | Description | Default |\\n|---------|-------------|---------|\\n| `maxPerTx` | Max USDC per single outbound op (send/pay) | 0 (unlimited) |\\n| `maxDailySend` | Max total USDC outbound per calendar day | 0 (unlimited) |\\n| `locked` | Kill switch \u2014 freezes ALL operations | false |\\n\\n## What counts as outbound\\n- `t2000 send` \u2014 transfers to other addresses\\n- `t2000 pay` \u2014 MPP API payments\\n\\n## What is NOT limited\\nInternal operations (save, withdraw, borrow, repay)\\nmove funds within the agent\'s own wallet and protocol positions. They\\nare not subject to send limits.\\n\\n## Output (config show)\\n```\\n Agent Safeguards\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Locked: No\\n Per-transaction: $500.00\\n Daily send limit: $1,000.00 ($350.00 used today)\\n```\\n\\n## Blocked output\\n```\\n \u2717 Blocked: amount $1,000.00 exceeds per-transaction limit ($500.00)\\n \u2717 Blocked: daily send limit reached ($1,000.00/$1,000.00 used today)\\n \u2717 Agent is locked. All operations frozen.\\n```\\n\\n## JSON mode\\n```bash\\nt2000 config show --json\\n```\\n```json\\n{ \\"locked\\": false, \\"maxPerTx\\": 500, \\"maxDailySend\\": 1000, \\"dailyUsed\\": 350 }\\n```\\n\\n## SDK\\n```typescript\\nconst agent = await T2000.create({ pin });\\n\\n// Check config\\nagent.enforcer.getConfig(); // { locked, maxPerTx, maxDailySend, dailyUsed, ... }\\nagent.enforcer.isConfigured(); // true if any limit is non-zero\\n\\n// Set limits\\nagent.enforcer.set(\'maxPerTx\', 500);\\nagent.enforcer.set(\'maxDailySend\', 1000);\\n\\n// Lock/unlock\\nagent.enforcer.lock();\\nagent.enforcer.unlock();\\n```\\n\\n## Important\\n- Safeguards are opt-in \u2014 defaults are permissive (0 = unlimited)\\n- MCP server requires non-zero limits before starting\\n- Lock freezes ALL operations (including internal) as a safety measure\\n- Daily counter resets at midnight UTC"},{"name":"t2000-save","description":"Deposit USDC or USDsui into savings to earn yield on Sui via NAVI Protocol. Use when asked to save money, earn interest, deposit to savings, \\"swap and save\\" a non-USDC token, or put funds to work. Not for sending to other addresses \u2014 use t2000-send for that.","body":"# t2000: Save (Deposit to Savings)\\n\\n## Purpose\\nDeposit **USDC or USDsui** into savings to earn yield on NAVI Protocol. Funds remain non-custodial and\\nwithdrawable at any time. USDsui is permitted as a strategic exception (v0.51.0+) because it has\\nits own NAVI pool, often at a different APY than USDC. Every other token (GOLD, SUI, USDT, USDe,\\nETH, NAVX, WAL) is **not saveable** \u2014 swap to USDC or USDsui first.\\n\\n## Command\\n```bash\\nt2000 save <amount> [--asset USDC|USDsui]\\nt2000 save all [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 save 80 # 80 USDC (default)\\nt2000 save 80 --asset USDsui # 80 USDsui\\nt2000 save all # full USDC balance (minus $1 gas reserve)\\nt2000 save all --asset USDsui # full USDsui balance (minus 1.0 reserve)\\n```\\n\\n- `save all`: deposits full available balance of the chosen asset minus 1.0 of that asset for safety\\n- `--asset` defaults to USDC when omitted\\n\\n## Fees\\n- Protocol fee: 0.1% on deposit (collected atomically on-chain)\\n\\n## Output\\n```\\n\u2713 Gas manager: $1.00 USDC \u2192 SUI [only shown if auto-topup triggered]\\n\u2713 Saved $XX.XX <asset> to best rate\\n\u2713 Current APY: X.XX%\\n\u2713 Savings balance: $XX.XX <asset>\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Notes\\n- APY is variable based on protocol utilization (USDC and USDsui pools quote independently)\\n- If available balance of the chosen asset is too low, returns INSUFFICIENT_BALANCE\\n- `t2000 supply` is an alias for `t2000 save`\\n- **Repay symmetry (v0.51.1+):** if you borrow USDsui, you must repay with USDsui (and USDC borrows must repay with USDC) \u2014 the SDK fetches the matching coin type per borrow asset.\\n\\n## Saving a non-USDC token (\\"swap and save\\")\\n\\nIf the user wants to save a token that\'s **not** USDC or USDsui \u2014 GOLD,\\nSUI, USDT, USDe, ETH, NAVX, WAL \u2014 the agent must swap first, then save.\\nThe right flow depends on the consumer:\\n\\n### Engine (audric/web) \u2014 bundled atomic swap + save\\n\\nEmit BOTH tool_use blocks in the SAME assistant turn. The engine\'s\\npermission gate compiles them into ONE Payment Intent: the swap\'s\\n`received` coin handles off as the save\'s input via coin-ref inside the\\nsame PTB. Atomic \u2014 both succeed or both revert. User signs once.\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: swap_execute({ from: \\"SUI\\", to: \\"USDC\\", amount: 1.0 })\\n tool_use: save_deposit({ amount: <swap_received>, asset: \\"USDC\\" })\\n```\\n\\nBefore emitting, **always preview** to the user:\\n- The source token + amount being swapped\\n- Estimated USDC received (from `swap_quote`)\\n- The save APY they\'ll earn\\n- Total fees (Cetus + Audric overlay + NAVI save fee)\\n\\n**Do NOT** call swap then save in separate turns \u2014 that loses atomicity\\nand exposes the user to price drift between the legs.\\n\\n**Do NOT** auto-decide for the user. If they say \\"save 10 SUI\\", confirm\\nthe intent: \\"That requires swapping ~10 SUI to ~$XX USDC first, then\\ndepositing. Proceed?\\" Some users want to hold SUI.\\n\\n### CLI \u2014 sequential (no bundling)\\n\\nThe CLI doesn\'t support Payment Intent bundling. Run two commands:\\n\\n```bash\\nt2000 swap 1.0 SUI to USDC\\nt2000 save all\\n```\\n\\nEach command prices against on-chain state at the moment of execution,\\nso there\'s small price drift between them. For large amounts ($1k+),\\nprefer the agent path which bundles into one Payment Intent.\\n\\n### What\'s NOT saveable\\n\\nGOLD, SUI, USDT, USDe, ETH, NAVX, WAL \u2014 none of these have NAVI lending\\npools today, so they can\'t be saved directly. Must swap to USDC or\\nUSDsui first. This is enforced by the SDK\'s `assertAllowedAsset(\'save\',\\nasset)` allow-list \u2014 calling `save_deposit({ asset: \'SUI\' })` returns\\n`UNSUPPORTED_ASSET`."},{"name":"t2000-send","description":"Send USDC from the t2000 agent wallet to another address on Sui. Use when asked to pay someone, transfer funds, send money, tip a creator, or make a payment to a specific Sui address or saved contact. Do NOT use for API payments \u2014 use t2000-pay for MPP-protected services.","body":"# t2000: Send USDC\\n\\n## Purpose\\nTransfer USDC from the agent\'s available balance to any Sui address. Gas is\\nself-funded from the agent\'s SUI reserve (auto-topped up if needed).\\n\\n## Command\\n```bash\\nt2000 send <amount> <asset> to <address_or_contact>\\nt2000 send <amount> <asset> <address_or_contact>\\n\\n# Examples:\\nt2000 send 10 USDC to 0x8b3e...d412\\nt2000 send 50 USDC to Tom\\nt2000 send 50 USDC 0xabcd...1234\\n```\\n\\nThe `to` keyword is optional. The recipient can be a Sui address (0x...) or a\\nsaved contact name (e.g. \\"Tom\\"). Use `t2000 contacts` to list saved contacts.\\n\\n## Pre-flight checks (automatic)\\n1. Sufficient available USDC balance\\n2. SUI gas reserve present; if not, auto-topup triggers transparently\\n\\n## Output\\n```\\n\u2713 Sent $XX.XX USDC \u2192 0x8b3e...d412\\n Gas: X.XXXX SUI (self-funded)\\n Balance: $XX.XX USDC\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Error handling\\n- `INSUFFICIENT_BALANCE`: available balance is less than the requested amount\\n- `INVALID_ADDRESS`: destination is not a valid Sui address\\n- `CONTACT_NOT_FOUND`: name is not a saved contact or valid address\\n- `SIMULATION_FAILED`: transaction would fail on-chain; details in error message\\n\\n## Recipient resolution flow\\n\\nWhen the user provides a recipient, resolve it before broadcasting:\\n\\n1. **Name given** \u2192 look up in saved contacts. If found, use the mapped\\n address. If not found and not a valid `0x...` address, ask the user\\n to clarify (suggest `t2000 contacts add <name> <address>` first).\\n2. **Address given (`0x...`)** \u2192 validate with `isValidSuiAddress()`. If\\n invalid, refuse with `INVALID_ADDRESS`.\\n3. **Ambiguous** (looks like a name AND a valid prefix) \u2192 ask the user\\n which they meant.\\n\\nAfter a successful send to a **previously-unknown raw address** (not a\\nsaved contact), offer to save it:\\n\\n> \\"Want to save 0x8b3e\u2026d412 as a contact? Say `yes <name>` to save.\\"\\n\\nIf the user provides a name, call `t2000 contacts add <name> <address>`\\n(CLI). This makes future sends to the same person work by name\\n(`t2000 send 10 USDC to <name>`). The engine no longer ships a\\n`save_contact` tool \u2014 contacts are CLI-only state today; audric users\\nmanage contacts via the send screen.\\n\\n**Do not auto-save** without asking \u2014 the user might not want every\\none-off recipient cluttering their contacts list.\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent:\\n\\n1. Resolve recipient (contacts lookup or address validation) \u2014 no tool call needed for contacts; resolution happens in prose.\\n2. Call `balance_check` to confirm sufficient funds.\\n3. Emit `send_transfer({ to, amount, asset })` as the write tool_use.\\n4. After the send settles, if the recipient was a raw address not already\\n in contacts, surface the \\"save as contact?\\" prompt to the user (see\\n above). The user confirms in the next turn; the host (CLI / audric)\\n handles persistence \u2014 the engine has no contact-write tool.\\n\\nSends are **single-write** \u2014 never bundle with another write in a\\nPayment Intent. Each transfer is its own intent."},{"name":"t2000-withdraw","description":"Withdraw from savings and receive USDC or USDsui. Use when asked to withdraw from savings, access deposited funds, pull money out of savings, reduce yield position, \\"close my position\\", or emergency withdraw. For sending to another address, use t2000-send.","body":"# t2000: Withdraw from Savings\\n\\n## Purpose\\nWithdraw USDC or USDsui from savings back to your checking balance.\\n\\n## Command\\n```bash\\nt2000 withdraw <amount> [--asset USDC|USDsui]\\nt2000 withdraw all [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 withdraw 25 # 25 USDC (default)\\nt2000 withdraw 25 --asset USDsui # 25 USDsui\\nt2000 withdraw all # full USDC savings position\\nt2000 withdraw all --asset USDsui # full USDsui savings position\\n```\\n\\n`--asset` defaults to USDC when omitted.\\n\\n## Fees\\n- No protocol fee on withdrawals\\n\\n## Output\\n```\\n\u2713 Withdrew $XX.XX <asset>\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Safety check (active when debt exists)\\n\\nIf the wallet has outstanding debt, t2000 evaluates whether the withdrawal\\nwould push the health factor below 1.5:\\n\\n| Scenario | Behavior |\\n|---|---|\\n| No debt | Withdrawal proceeds \u2014 no HF check. |\\n| Withdrawal keeps HF \u2265 1.5 | Withdrawal proceeds \u2014 note the new HF in the output. |\\n| Withdrawal would drop HF < 1.5 | **Refused** with `WITHDRAW_WOULD_LIQUIDATE`. Error data includes `safeWithdrawAmount` (the largest amount that keeps HF \u2265 1.5). |\\n\\n## Emergency / \\"close my position\\" flow\\n\\nWhen the user asks to \\"withdraw everything\\", \\"close my position\\", or\\n\\"emergency withdraw\\":\\n\\n### Step 1 \u2014 Read state\\nCall `health_check` (engine) or `t2000 balance --show-limits` (CLI) to\\nsee savings, debt, and current HF.\\n\\n### Step 2 \u2014 Decide path\\n\\n| Wallet state | Path |\\n|---|---|\\n| **No debt** | Single-write `withdraw all` for each asset held in savings. |\\n| **Has debt, savings \u2265 debt** | **Bundled repay + withdraw** \u2014 emit `repay_debt(all)` and `withdraw(remaining)` as parallel `tool_use` blocks in the SAME assistant turn. Engine compiles into one Payment Intent: atomic repay-then-withdraw, one signature. |\\n| **Has debt, savings < debt** | **Refuse** \u2014 user can\'t fully close position without first acquiring more of the borrowed asset. Tell them how much more they\'d need; do not auto-swap. |\\n\\n### Step 3 \u2014 Bundled emit (engine path)\\n\\nFor the \\"bundled repay + withdraw\\" case, emit BOTH tool_use blocks in the\\nsame assistant turn:\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: repay_debt({ amount: <debt>, asset: <borrowed_asset> })\\n tool_use: withdraw({ amount: <remaining>, asset: <savings_asset> })\\n```\\n\\nThe engine\'s permission gate compiles these into ONE Payment Intent. Both\\nlegs succeed or both revert \u2014 no partial close. The user signs once.\\n\\n**Do NOT** call them sequentially across turns \u2014 that loses atomicity and\\nexposes the user to a window where debt is repaid but the withdraw fails,\\nleaving the wallet in an awkward state.\\n\\n**Critical:** `repay_debt` MUST use the SAME asset as the original borrow\\n(USDsui debt \u2192 USDsui repay, USDC debt \u2192 USDC repay \u2014 see `t2000-repay`).\\nIf the user doesn\'t hold enough of the matching asset, abort with a clear\\nmessage; do not auto-swap.\\n\\n## Error handling\\n- `WITHDRAW_WOULD_LIQUIDATE` \u2014 withdrawal would push HF < 1.5. Use `safeWithdrawAmount` from error data, or repay debt first.\\n- `NO_COLLATERAL` \u2014 no savings position in the requested asset.\\n- `INSUFFICIENT_BALANCE` \u2014 requested amount exceeds savings balance.\\n- Intent failed (bundled flow) \u2014 atomic revert. No funds moved."}]';
141301
+ const raw = '[{"name":"mpp-gpt4o","description":"Call GPT-4o (or any OpenAI chat model) via `t2000 pay` against the MPP-protected endpoint at https://mpp.t2000.ai/openai/v1/chat/completions. Use when asked to \\"ask GPT\\", summarize text, answer a question, extract structured data, classify, translate (when DeepL is overkill), or chain reasoning through a hosted LLM. Pay-per-request (~$0.01 USDC). No API key, no account. Returns standard OpenAI Chat Completions response shape.","body":"# MPP Recipe: GPT-4o Chat Completions\\n\\n## When to use\\n\\nThe user asks for any of:\\n\\n- \\"Ask GPT / ask ChatGPT / ask 4o \u2026\\"\\n- \\"Summarize this article \u2026\\"\\n- \\"Extract names from this text \u2026\\"\\n- \\"Classify these support tickets \u2026\\"\\n- \\"Translate (and DeepL isn\'t right \u2014 e.g., needs context, idiom, or chain-of-thought)\\"\\n\\nFor image generation use `mpp-image-gen`. For audio \u2192 text use `mpp-transcription`. For cheaper text models see Together AI / Mistral / DeepSeek in `mpp-index`.\\n\\n## Rules\\n\\n1. **Don\'t pay for a chat call you can do with Claude (the local LLM you\'re running inside) for free.** Use `t2000 pay` against `/openai/v1/chat/completions` only when the user EXPLICITLY wants GPT-4o, or when the local model can\'t see the content (e.g., a URL that requires GPT-4o vision).\\n2. **Always pass `model` explicitly.** Default upstream selection drifts. Common: `gpt-4o`, `gpt-4o-mini` (10x cheaper but still $0.01 per call in MPP pricing), `o1-mini`.\\n3. **Bound `max_tokens` for unbounded prompts.** Without it, GPT can run 4096 tokens and you pay full price for filler. Set 200-500 for summarization, 50-100 for classification.\\n4. **No streaming over `t2000 pay`.** The CLI returns the final JSON; if you need a streaming UX, switch to direct SDK use (`mppx`).\\n5. **One request = one paid call.** Multi-turn conversations cost $0.01 per turn \u2014 surface this if you expect > 10 turns.\\n\\n## The fast path\\n\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\n \\"model\\": \\"gpt-4o\\",\\n \\"messages\\": [\\n {\\"role\\": \\"user\\", \\"content\\": \\"Summarize the Sui consensus algorithm in 3 sentences.\\"}\\n ],\\n \\"max_tokens\\": 200\\n }\'\\n```\\n\\n## Returns\\n\\n```json\\n{\\n \\"id\\": \\"chatcmpl-...\\",\\n \\"object\\": \\"chat.completion\\",\\n \\"created\\": 1716700000,\\n \\"model\\": \\"gpt-4o-2024-08-06\\",\\n \\"choices\\": [\\n {\\n \\"index\\": 0,\\n \\"message\\": {\\"role\\": \\"assistant\\", \\"content\\": \\"Sui uses ...\\"},\\n \\"finish_reason\\": \\"stop\\"\\n }\\n ],\\n \\"usage\\": {\\"prompt_tokens\\": 14, \\"completion_tokens\\": 87, \\"total_tokens\\": 101}\\n}\\n```\\n\\n**Key field:** `choices[0].message.content` \u2014 the assistant reply. Extract with `jq -r \'.choices[0].message.content\'` for piping.\\n\\n## Tuning knobs\\n\\n| Field | Default | When to set |\\n|---|---|---|\\n| `model` | `gpt-4o` | `gpt-4o-mini` for cost-sensitive batches (same $0.01 in MPP, but faster). `o1-preview` / `o1-mini` for reasoning tasks. |\\n| `temperature` | `1.0` | `0` for deterministic (classification, extraction). `0.7` for creative. |\\n| `max_tokens` | upstream default (long!) | Always set for predictable spend + latency. |\\n| `messages[].role` | \u2014 | Standard `system` / `user` / `assistant` chain. Multi-turn supported. |\\n\\n## Common patterns\\n\\n**Classify support tickets (deterministic):**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\n \\"model\\": \\"gpt-4o-mini\\",\\n \\"temperature\\": 0,\\n \\"max_tokens\\": 20,\\n \\"messages\\": [\\n {\\"role\\": \\"system\\", \\"content\\": \\"Classify the ticket as one of: BILLING, BUG, FEATURE, OTHER. Reply with one word.\\"},\\n {\\"role\\": \\"user\\", \\"content\\": \\"My card was charged twice last week\\"}\\n ]\\n }\'\\n```\\n\\n**Vision \u2014 describe an image URL:**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\n \\"model\\": \\"gpt-4o\\",\\n \\"max_tokens\\": 300,\\n \\"messages\\": [{\\n \\"role\\": \\"user\\",\\n \\"content\\": [\\n {\\"type\\": \\"text\\", \\"text\\": \\"What is in this image? Be specific about the architectural style.\\"},\\n {\\"type\\": \\"image_url\\", \\"image_url\\": {\\"url\\": \\"https://example.com/building.jpg\\"}}\\n ]\\n }]\\n }\'\\n```\\n\\n**Structured extraction (JSON mode):**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\n \\"model\\": \\"gpt-4o\\",\\n \\"max_tokens\\": 500,\\n \\"messages\\": [\\n {\\"role\\": \\"system\\", \\"content\\": \\"Extract every person mentioned. Reply with valid JSON only: {\\\\\\"people\\\\\\": [{\\\\\\"name\\\\\\": \\\\\\"...\\\\\\", \\\\\\"role\\\\\\": \\\\\\"...\\\\\\"}]}\\"},\\n {\\"role\\": \\"user\\", \\"content\\": \\"Alice (CEO) and Bob (CTO) met with Carol from Acme.\\"}\\n ]\\n }\'\\n```\\n\\nThen `jq \'.choices[0].message.content | fromjson\'` to parse.\\n\\n**Summarize a scraped page (chain with Firecrawl):**\\n```bash\\n# Step 1: scrape ($0.01)\\nCONTENT=$(t2000 pay https://mpp.t2000.ai/firecrawl/v1/scrape \\\\\\n --data \'{\\"url\\":\\"https://example.com/article\\"}\' \\\\\\n --json | jq -r \'.data.markdown\')\\n\\n# Step 2: summarize ($0.01)\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \\"$(jq -nc --arg c \\"$CONTENT\\" \'{\\n model: \\"gpt-4o\\",\\n max_tokens: 300,\\n messages: [\\n {role: \\"system\\", content: \\"Summarize in 5 bullets.\\"},\\n {role: \\"user\\", content: $c}\\n ]\\n }\')\\"\\n```\\n\\n## Cost guard\\n\\n- **Per-call pricing is fixed at $0.01** in MPP regardless of input/output tokens. The gateway absorbs token-level variance.\\n- **Default `--max-price`**: `$1.00`. Covers 100 calls. For chat sessions, batch within a single request when possible (pass the full message history rather than re-paying per turn).\\n\\n## Errors\\n\\n- `PRICE_EXCEEDS_LIMIT` \u2014 `--max-price` < $0.01. Default $1.00 should never hit this.\\n- `INSUFFICIENT_BALANCE` \u2014 top up with `t2000 fund`.\\n- `400 content_policy_violation` \u2014 OpenAI safety filter. You\'re still charged (OpenAI behavior). Reword.\\n- `429 rate_limit_exceeded` \u2014 OpenAI upstream is rate-limited. Wait 10s and retry. Payment is one-shot per request.\\n\\n## What NOT to do\\n\\n- Don\'t chain GPT-4o calls for tasks Claude (local) handles well \u2014 wastes USDC on commodity reasoning.\\n- Don\'t poll for streaming. The MPP gateway is request/response.\\n- Don\'t pass secrets in `messages` content. Treat every paid call as if logged.\\n\\n## Related recipes\\n\\n- `mpp-image-gen` \u2014 image generation via OpenAI.\\n- `mpp-transcription` \u2014 audio \u2192 text via OpenAI Whisper.\\n- `mpp-index` \u2014 discovery for cheaper alternatives (Together AI, Mistral, Groq).\\n- `t2000-pay` \u2014 generic `t2000 pay` reference."},{"name":"mpp-image-gen","description":"Generate an image via `t2000 pay` against the MPP-protected OpenAI gpt-image-1 endpoint at https://mpp.t2000.ai/openai/v1/images/generations. Use when asked to make/generate/create an image, illustration, banner, thumbnail, profile pic, logo, mockup, or \\"draw\\" something. Pay-per-image (~$0.05 USDC, no API key, no account). Returns a permanent URL hosted on Vercel Blob \u2014 safe to embed in chat or hand to downstream tools.","body":"# MPP Recipe: Generate an Image\\n\\n## When to use\\n\\nThe user asks for any of:\\n\\n- \\"Generate an image of \u2026\\"\\n- \\"Make me a thumbnail / banner / hero / illustration of \u2026\\"\\n- \\"Draw / paint / render \u2026\\"\\n- \\"Create a profile picture / avatar of \u2026\\"\\n\\nFor text-to-text generation use `mpp-gpt4o`. For audio \u2192 text use `mpp-transcription`. For voice (TTS) use the direct `/openai/v1/audio/speech` recipe under `mpp-index`.\\n\\n## Rules\\n\\n1. **One paid request per image.** Don\'t loop \\"make 5 variants\\" into 5 separate calls \u2014 pass `n: 4` (max 4) inside one request. You still pay per-image but it\'s atomic.\\n2. **Confirm the prompt before paying.** Generation is paid + irreversible. Surface the prompt + estimated cost (`$0.05 \xD7 n`) and let the user approve.\\n3. **Don\'t auto-upscale or re-style.** If the result isn\'t quite right, ASK before regenerating \u2014 each retry is another $0.05.\\n4. **Use the returned URL directly.** The gateway uploads each image to Vercel Blob and rewrites the response to `{ data: [{ url }] }` shape. Don\'t try to decode base64 \u2014 that path is invalid for `gpt-image-1`.\\n5. **Size matters.** Default is `1024x1024` (~$0.05). Larger sizes (`1024x1792`, `1792x1024`) cost the same per image but render slower. Pick `1024x1024` unless the user explicitly needs portrait/landscape.\\n\\n## The fast path\\n\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/images/generations \\\\\\n --data \'{\\n \\"prompt\\": \\"a serene mountain lake at dawn, cinematic lighting, photorealistic\\",\\n \\"size\\": \\"1024x1024\\"\\n }\'\\n```\\n\\nThat\'s it. The MPP 402 challenge is handled automatically; payment broadcasts to Sui mainnet; OpenAI generates; gateway uploads to Blob; you get back JSON with a URL.\\n\\n## Returns\\n\\n```json\\n{\\n \\"data\\": [\\n {\\n \\"url\\": \\"https://<blob-store>.public.blob.vercel-storage.com/<id>.png\\"\\n }\\n ]\\n}\\n```\\n\\n**Key field:** `data[0].url` \u2014 permanent CDN URL. Survives indefinitely. Embed in markdown as `![](url)` for chat surfaces.\\n\\n## Tuning knobs\\n\\n| Field | Default | When to set |\\n|---|---|---|\\n| `model` | `gpt-image-1` | Pass `\\"gpt-image-1-mini\\"` for cheaper/faster (still $0.05 in gateway pricing today, but quality lower; consider for low-stakes thumbnails). |\\n| `size` | `1024x1024` | Use `1024x1792` for portrait (story / book cover / phone wallpaper). Use `1792x1024` for landscape (banner / hero image). |\\n| `n` | `1` | Set up to 4 to get variants in one call. Cost is `0.05 \xD7 n`. |\\n\\n## Common patterns\\n\\n**Banner with text overlay** (the gateway can\'t add text; ask the model):\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/images/generations \\\\\\n --data \'{\\n \\"prompt\\": \\"Modern tech conference banner, bold text \\\\\\"AGENTIC FINANCE\\\\\\" centered, blue and white palette, minimalist\\",\\n \\"size\\": \\"1792x1024\\"\\n }\'\\n```\\n\\n**4 variants of a profile pic**:\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/images/generations \\\\\\n --max-price 0.25 \\\\\\n --data \'{\\n \\"prompt\\": \\"Pixar-style 3D portrait of a friendly cyberpunk fox, blue accent lighting\\",\\n \\"n\\": 4\\n }\'\\n```\\n\\nNote the `--max-price 0.25` \u2014 you must raise the cap above $0.05 since the request charges `0.05 \xD7 4 = 0.20` USDC.\\n\\n**Generate then describe** (image \u2192 caption via two paid calls):\\n```bash\\n# Step 1: generate\\nIMG_URL=$(t2000 pay https://mpp.t2000.ai/openai/v1/images/generations --json \\\\\\n --data \'{\\"prompt\\": \\"futuristic neon-lit Tokyo alley\\"}\' | jq -r \'.data[0].url\')\\n\\n# Step 2: describe via GPT-4o vision\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \\"{\\\\\\"model\\\\\\":\\\\\\"gpt-4o\\\\\\",\\\\\\"messages\\\\\\":[{\\\\\\"role\\\\\\":\\\\\\"user\\\\\\",\\\\\\"content\\\\\\":[{\\\\\\"type\\\\\\":\\\\\\"text\\\\\\",\\\\\\"text\\\\\\":\\\\\\"Caption this image in one sentence.\\\\\\"},{\\\\\\"type\\\\\\":\\\\\\"image_url\\\\\\",\\\\\\"image_url\\\\\\":{\\\\\\"url\\\\\\":\\\\\\"$IMG_URL\\\\\\"}}]}]}\\"\\n```\\n\\n## Cost guard\\n\\n- **Default `--max-price`**: `$1.00`. A single 1024x1024 image is $0.05, so the default covers up to 20 images. For batch jobs > 4 images, set explicitly.\\n- **Per-image pricing is fixed at $0.05** regardless of size or model in current MPP pricing.\\n\\n## Errors\\n\\n- `PRICE_EXCEEDS_LIMIT` \u2014 your `--max-price` is below the requested cost. Bump it.\\n- `INSUFFICIENT_BALANCE` \u2014 not enough USDC in the wallet. Run `t2000 fund` to top up.\\n- `400 invalid_prompt` \u2014 OpenAI refused the prompt (safety filter). Reword and retry; you\'ll be charged again on retry \u2014 this is OpenAI\'s behavior, not ours.\\n\\n## What NOT to do\\n\\n- Don\'t ask the agent to \\"generate 100 images\\" without surfacing the cost ($5 USDC). The user should approve any batch > 4.\\n- Don\'t poll-loop on a failed generation. If OpenAI returns a 400, the gateway already collected payment; retrying without changing the prompt repeats the same charge.\\n- Don\'t try to fetch the image URL through `t2000 pay` again. The returned URL is public CDN and free to GET.\\n\\n## Related recipes\\n\\n- `mpp-gpt4o` \u2014 text generation, summarization, vision (image understanding).\\n- `mpp-index` \u2014 discovery page for every other MPP service (40 total).\\n- `t2000-pay` \u2014 generic technical reference for the `t2000 pay` command."},{"name":"mpp-index","description":"Intent-grouped discovery page for every MPP-protected service at mpp.t2000.ai. Use when picking a service: scan by \\"what I want to do\\", copy the one-line example, refine with the dedicated recipe (if one exists) or `t2000-pay`. 40 services, 88 endpoints, all payable with Sui USDC via `t2000 pay`. No API keys. No accounts.","body":"# MPP Recipe Index\\n\\nQuick scan: find a service by what you\'re trying to do.\\n\\n**Dedicated recipes** (open these for full details):\\n- \u{1F5BC}\uFE0F `mpp-image-gen` \u2014 OpenAI image generation ($0.05)\\n- \u{1F4AC} `mpp-gpt4o` \u2014 OpenAI chat completions ($0.01)\\n- \u{1F399}\uFE0F `mpp-transcription` \u2014 OpenAI Whisper transcription ($0.01)\\n\\nEverything else lives in this index with a one-line working example.\\n\\nFor the live, canonical service list call `t2000_services` (MCP) or `GET https://mpp.t2000.ai/api/services`.\\n\\n---\\n\\n## \u{1F9E0} I want to ask an LLM / generate text\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Hosted GPT-4o (deep, multimodal) | OpenAI Chat | $0.01 | See `mpp-gpt4o` |\\n| Cheaper / faster general LLM | Together AI Chat | $0.005 | `t2000 pay https://mpp.t2000.ai/together/v1/chat/completions --data \'{\\"model\\":\\"meta-llama/Llama-3.3-70B-Instruct-Turbo\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"\u2026\\"}]}\'` |\\n| Even cheaper, reasoning-strong | DeepSeek | $0.005 | `t2000 pay https://mpp.t2000.ai/deepseek/v1/chat/completions --data \'{\\"model\\":\\"deepseek-chat\\",\\"messages\\":[\u2026]}\'` |\\n| Fastest inference (groq) | Groq Chat | $0.005 | `t2000 pay https://mpp.t2000.ai/groq/v1/chat/completions --data \'{\\"model\\":\\"llama-3.3-70b-versatile\\",\\"messages\\":[\u2026]}\'` |\\n| Search-grounded answers | Perplexity | $0.01 | `t2000 pay https://mpp.t2000.ai/perplexity/v1/chat/completions --data \'{\\"model\\":\\"sonar\\",\\"messages\\":[\u2026]}\'` |\\n| Claude (long context, careful reasoning) | Anthropic | $0.01 | `t2000 pay https://mpp.t2000.ai/anthropic/v1/messages --data \'{\\"model\\":\\"claude-3-5-sonnet-latest\\",\\"max_tokens\\":500,\\"messages\\":[\u2026]}\'` |\\n| Gemini (free upstream tier, multimodal) | Google Gemini Flash | $0.005 | `t2000 pay https://mpp.t2000.ai/gemini/v1beta/models/gemini-2.5-flash --data \'{\\"contents\\":[{\\"parts\\":[{\\"text\\":\\"\u2026\\"}]}]}\'` |\\n| EU-hosted, low-latency | Mistral | $0.005 | `t2000 pay https://mpp.t2000.ai/mistral/v1/chat/completions --data \'{\\"model\\":\\"mistral-large-latest\\",\\"messages\\":[\u2026]}\'` |\\n| Multilingual + reranking | Cohere | $0.005 | `t2000 pay https://mpp.t2000.ai/cohere/v1/chat --data \'{\\"message\\":\\"\u2026\\",\\"model\\":\\"command-r-plus\\"}\'` |\\n\\n## \u{1F50D} I want embeddings (vector search)\\n\\n| Service | Price | One-liner |\\n|---|---|---|\\n| OpenAI Embeddings | $0.005 | `t2000 pay https://mpp.t2000.ai/openai/v1/embeddings --data \'{\\"model\\":\\"text-embedding-3-small\\",\\"input\\":\\"\u2026\\"}\'` |\\n| Together AI Embeddings | $0.005 | `t2000 pay https://mpp.t2000.ai/together/v1/embeddings --data \'{\\"model\\":\\"BAAI/bge-large-en-v1.5\\",\\"input\\":\\"\u2026\\"}\'` |\\n| Mistral Embeddings | $0.005 | `t2000 pay https://mpp.t2000.ai/mistral/v1/embeddings --data \'{\\"model\\":\\"mistral-embed\\",\\"input\\":[\\"\u2026\\"]}\'` |\\n| Cohere Embed | $0.005 | `t2000 pay https://mpp.t2000.ai/cohere/v1/embed --data \'{\\"texts\\":[\\"\u2026\\"],\\"model\\":\\"embed-english-v3.0\\",\\"input_type\\":\\"search_document\\"}\'` |\\n| Cohere Rerank | $0.005 | `t2000 pay https://mpp.t2000.ai/cohere/v1/rerank --data \'{\\"query\\":\\"\u2026\\",\\"documents\\":[\\"\u2026\\",\\"\u2026\\"],\\"model\\":\\"rerank-v3.5\\"}\'` |\\n| Gemini Embeddings | $0.005 | `t2000 pay https://mpp.t2000.ai/gemini/v1beta/models/embedding-001 --data \'{\\"content\\":{\\"parts\\":[{\\"text\\":\\"\u2026\\"}]}}\'` |\\n\\n## \u{1F5BC}\uFE0F I want to generate an image\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Highest quality (default) | OpenAI gpt-image-1 | $0.05 | See `mpp-image-gen` |\\n| Cheap / open-weights | Fal.ai Flux Dev | $0.03 | `t2000 pay https://mpp.t2000.ai/fal/fal-ai/flux/dev --data \'{\\"prompt\\":\\"\u2026\\"}\'` |\\n| Premium quality | Fal.ai Flux Pro | $0.05 | `t2000 pay https://mpp.t2000.ai/fal/fal-ai/flux-pro --data \'{\\"prompt\\":\\"\u2026\\"}\'` |\\n| Photorealistic | Fal.ai Flux Realism | $0.05 | `t2000 pay https://mpp.t2000.ai/fal/fal-ai/flux-realism --data \'{\\"prompt\\":\\"\u2026\\"}\'` |\\n| Vector / illustration | Fal.ai Recraft 20B | $0.05 | `t2000 pay https://mpp.t2000.ai/fal/fal-ai/recraft-20b --data \'{\\"prompt\\":\\"\u2026\\",\\"style\\":\\"vector_illustration\\"}\'` |\\n| Together AI (batch-friendly) | Together AI Images | $0.03 | `t2000 pay https://mpp.t2000.ai/together/v1/images/generations --data \'{\\"model\\":\\"black-forest-labs/FLUX.1-schnell-Free\\",\\"prompt\\":\\"\u2026\\"}\'` |\\n| Stability AI (Stable Diffusion 3) | Stability Generate | $0.03 | `t2000 pay https://mpp.t2000.ai/stability/v1/generate --data \'{\\"prompt\\":\\"\u2026\\"}\'` |\\n| Edit an existing image | Stability Edit | $0.03 | `t2000 pay https://mpp.t2000.ai/stability/v1/edit --data \'{\\"image\\":\\"https://\u2026\\",\\"prompt\\":\\"add a red hat\\"}\'` |\\n| Any model on Replicate | Replicate | $0.02 | `t2000 pay https://mpp.t2000.ai/replicate/v1/predictions --data \'{\\"model\\":\\"black-forest-labs/flux-dev\\",\\"input\\":{\\"prompt\\":\\"\u2026\\"}}\'` |\\n\\n## \u{1F399}\uFE0F I want speech / audio\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Transcribe audio (default) | OpenAI Whisper | $0.01 | See `mpp-transcription` |\\n| Transcribe + diarize | AssemblyAI | $0.02 | `t2000 pay https://mpp.t2000.ai/assemblyai/v1/transcribe --max-price 0.05 --data \'{\\"audio_url\\":\\"\u2026\\",\\"speaker_labels\\":true}\'` (then poll `/assemblyai/v1/result` $0.005) |\\n| Cheaper / faster transcription | Groq Whisper | $0.005 | `t2000 pay https://mpp.t2000.ai/groq/v1/audio/transcriptions --data \'{\\"file\\":\\"\u2026\\",\\"model\\":\\"whisper-large-v3\\"}\'` |\\n| Open-source Whisper | Fal.ai Whisper | $0.01 | `t2000 pay https://mpp.t2000.ai/fal/fal-ai/whisper --data \'{\\"audio_url\\":\\"\u2026\\"}\'` |\\n| Text \u2192 speech (OpenAI) | OpenAI TTS | $0.02 | `t2000 pay https://mpp.t2000.ai/openai/v1/audio/speech --data \'{\\"model\\":\\"tts-1\\",\\"input\\":\\"Hello\\",\\"voice\\":\\"alloy\\"}\'` |\\n| Text \u2192 speech (premium voices) | ElevenLabs TTS | $0.05 | `t2000 pay https://mpp.t2000.ai/elevenlabs/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM --data \'{\\"text\\":\\"Hello\\"}\'` |\\n| Sound effects | ElevenLabs SFX | $0.05 | `t2000 pay https://mpp.t2000.ai/elevenlabs/v1/sound-generation --data \'{\\"text\\":\\"rain on a tin roof\\"}\'` |\\n\\n## \u{1F310} I want to search the web\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Web search | Brave Web | $0.005 | `t2000 pay https://mpp.t2000.ai/brave/v1/web/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| Image search | Brave Image | $0.005 | `t2000 pay https://mpp.t2000.ai/brave/v1/images/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| News search | Brave News | $0.005 | `t2000 pay https://mpp.t2000.ai/brave/v1/news/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| Video search | Brave Video | $0.005 | `t2000 pay https://mpp.t2000.ai/brave/v1/videos/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| LLM summary of search | Brave Summarizer | $0.01 | `t2000 pay https://mpp.t2000.ai/brave/v1/summarizer/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| Google search (structured) | Serper | $0.005 | `t2000 pay https://mpp.t2000.ai/serper/v1/search --data \'{\\"q\\":\\"\u2026\\"}\'` |\\n| Google Flights | SerpAPI | $0.01 | `t2000 pay https://mpp.t2000.ai/serpapi/v1/flights --data \'{\\"departure_id\\":\\"LAX\\",\\"arrival_id\\":\\"NRT\\",\\"outbound_date\\":\\"2026-07-01\\",\\"type\\":\\"2\\"}\'` |\\n| Semantic search (neural) | Exa | $0.01 | `t2000 pay https://mpp.t2000.ai/exa/v1/search --data \'{\\"query\\":\\"\u2026\\",\\"numResults\\":5}\'` |\\n| Get page content | Exa Contents | $0.01 | `t2000 pay https://mpp.t2000.ai/exa/v1/contents --data \'{\\"urls\\":[\\"https://\u2026\\"]}\'` |\\n| News headlines | NewsAPI | $0.005 | `t2000 pay https://mpp.t2000.ai/newsapi/v1/headlines --data \'{\\"country\\":\\"us\\"}\'` |\\n\\n## \u{1F4C4} I want to read / scrape a page\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Scrape single page (markdown) | Firecrawl Scrape | $0.01 | `t2000 pay https://mpp.t2000.ai/firecrawl/v1/scrape --data \'{\\"url\\":\\"https://\u2026\\"}\'` |\\n| Crawl whole site | Firecrawl Crawl | $0.02 | `t2000 pay https://mpp.t2000.ai/firecrawl/v1/crawl --data \'{\\"url\\":\\"https://\u2026\\",\\"limit\\":50}\'` |\\n| Map site URLs | Firecrawl Map | $0.01 | `t2000 pay https://mpp.t2000.ai/firecrawl/v1/map --data \'{\\"url\\":\\"https://\u2026\\"}\'` |\\n| Extract structured data | Firecrawl Extract | $0.02 | `t2000 pay https://mpp.t2000.ai/firecrawl/v1/extract --data \'{\\"urls\\":[\\"https://\u2026\\"],\\"schema\\":{\u2026}}\'` |\\n| Plain reader (markdown) | Jina Reader | $0.005 | `t2000 pay https://mpp.t2000.ai/jina/v1/read --data \'{\\"url\\":\\"https://\u2026\\"}\'` |\\n| Screenshot a page | ScreenshotOne | $0.01 | `t2000 pay https://mpp.t2000.ai/screenshot/v1/capture --data \'{\\"url\\":\\"https://\u2026\\",\\"format\\":\\"png\\"}\'` |\\n| HTML \u2192 PDF | PDFShift | $0.01 | `t2000 pay https://mpp.t2000.ai/pdfshift/v1/convert --data \'{\\"source\\":\\"https://\u2026\\"}\'` |\\n| QR code | QR Code | $0.005 | `t2000 pay https://mpp.t2000.ai/qrcode/v1/generate --data \'{\\"data\\":\\"https://\u2026\\",\\"size\\":\\"400x400\\"}\'` |\\n\\n## \u{1F30D} I want translation\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Highest quality | DeepL | $0.005 | `t2000 pay https://mpp.t2000.ai/deepl/v1/translate --data \'{\\"text\\":[\\"Hello\\"],\\"target_lang\\":\\"ES\\"}\'` |\\n| Google Translate | Google Translate | $0.005 | `t2000 pay https://mpp.t2000.ai/translate/v1/translate --data \'{\\"q\\":\\"Hello\\",\\"target\\":\\"es\\"}\'` |\\n| Detect language | Google Detect | $0.005 | `t2000 pay https://mpp.t2000.ai/translate/v1/detect --data \'{\\"q\\":\\"Bonjour\\"}\'` |\\n\\n## \u{1F4CA} I want data (weather, maps, crypto, stocks)\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Current weather | OpenWeather | $0.005 | `t2000 pay https://mpp.t2000.ai/openweather/v1/weather --data \'{\\"q\\":\\"Tokyo\\"}\'` |\\n| Forecast | OpenWeather Forecast | $0.005 | `t2000 pay https://mpp.t2000.ai/openweather/v1/forecast --data \'{\\"q\\":\\"Tokyo\\"}\'` |\\n| Geocode address | Google Maps Geocode | $0.01 | `t2000 pay https://mpp.t2000.ai/googlemaps/v1/geocode --data \'{\\"address\\":\\"1 Hacker Way, Menlo Park\\"}\'` |\\n| Search places | Google Maps Places | $0.01 | `t2000 pay https://mpp.t2000.ai/googlemaps/v1/places --data \'{\\"query\\":\\"coffee in Tokyo\\"}\'` |\\n| Directions | Google Maps Directions | $0.01 | `t2000 pay https://mpp.t2000.ai/googlemaps/v1/directions --data \'{\\"origin\\":\\"SF\\",\\"destination\\":\\"Palo Alto\\"}\'` |\\n| Crypto price | CoinGecko Price | $0.005 | `t2000 pay https://mpp.t2000.ai/coingecko/v1/price --data \'{\\"ids\\":\\"sui,bitcoin\\",\\"vs_currencies\\":\\"usd\\"}\'` |\\n| Crypto market | CoinGecko Markets | $0.005 | `t2000 pay https://mpp.t2000.ai/coingecko/v1/markets --data \'{\\"vs_currency\\":\\"usd\\",\\"ids\\":\\"sui\\"}\'` |\\n| Stock quote | Alpha Vantage | $0.005 | `t2000 pay https://mpp.t2000.ai/alphavantage/v1/quote --data \'{\\"symbol\\":\\"AAPL\\"}\'` |\\n| Currency conversion | ExchangeRate | $0.005 | `t2000 pay https://mpp.t2000.ai/exchangerate/v1/convert --data \'{\\"from\\":\\"USD\\",\\"to\\":\\"EUR\\",\\"amount\\":100}\'` |\\n\\n## \u2709\uFE0F I want to send / message / mail\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Send email | Resend | $0.005 | `t2000 pay https://mpp.t2000.ai/resend/v1/emails --data \'{\\"from\\":\\"agent@t2000.ai\\",\\"to\\":\\"\u2026\\",\\"subject\\":\\"\u2026\\",\\"text\\":\\"\u2026\\"}\'` |\\n| Send batch email | Resend Batch | $0.01 | `t2000 pay https://mpp.t2000.ai/resend/v1/emails/batch --data \'[{\\"from\\":\\"\u2026\\",\\"to\\":\\"\u2026\\",\\"subject\\":\\"\u2026\\",\\"text\\":\\"\u2026\\"}]\'` |\\n| Push notification | Pushover | $0.005 | `t2000 pay https://mpp.t2000.ai/pushover/v1/push --data \'{\\"user\\":\\"USER_KEY\\",\\"message\\":\\"\u2026\\"}\'` |\\n| Send a postcard | Lob Postcards | $1.00 | `t2000 pay https://mpp.t2000.ai/lob/v1/postcards --max-price 2 --data \'{\\"to\\":{\u2026},\\"from\\":{\u2026},\\"front\\":\\"https://\u2026\\",\\"back\\":\\"https://\u2026\\",\\"use_type\\":\\"operational\\"}\'` |\\n| Send a physical letter | Lob Letters | $1.50 | `t2000 pay https://mpp.t2000.ai/lob/v1/letters --max-price 2 --data \'{\\"to\\":{\u2026},\\"from\\":{\u2026},\\"file\\":\\"https://\u2026\\",\\"use_type\\":\\"operational\\"}\'` |\\n| Verify US address | Lob Verify | $0.01 | `t2000 pay https://mpp.t2000.ai/lob/v1/verify --data \'{\\"primary_line\\":\\"123 Main St\\",\\"city\\":\\"SF\\",\\"state\\":\\"CA\\",\\"zip_code\\":\\"94105\\"}\'` |\\n\\n## \u{1F6D2} I want commerce / fulfillment\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Print-on-demand catalog | Printful Browse | $0.005 | `t2000 pay https://mpp.t2000.ai/printful/v1/products` |\\n| Shipping estimate | Printful Estimate | $0.005 | `t2000 pay https://mpp.t2000.ai/printful/v1/estimate --data \'{\\"recipient\\":{\u2026},\\"items\\":[{\u2026}]}\'` |\\n| Place an order | Printful Order | dynamic | `t2000 pay https://mpp.t2000.ai/printful/v1/order --max-price 30 --data \'{\\"recipient\\":{\u2026},\\"items\\":[{\u2026}]}\'` |\\n\\n## \u{1F50E} I want intelligence / OSINT\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Find emails for a domain | Hunter.io Search | $0.02 | `t2000 pay https://mpp.t2000.ai/hunter/v1/search --data \'{\\"domain\\":\\"\u2026\\"}\'` |\\n| Verify email | Hunter.io Verify | $0.02 | `t2000 pay https://mpp.t2000.ai/hunter/v1/verify --data \'{\\"email\\":\\"\u2026\\"}\'` |\\n| Look up IP | IPinfo | $0.005 | `t2000 pay https://mpp.t2000.ai/ipinfo/v1/lookup --data \'{\\"ip\\":\\"8.8.8.8\\"}\'` |\\n| Scan URL for malware | VirusTotal | $0.01 | `t2000 pay https://mpp.t2000.ai/virustotal/v1/scan --data \'{\\"url\\":\\"https://\u2026\\"}\'` |\\n\\n## \u{1F6E0}\uFE0F I want to run code / tools\\n\\n| Use case | Service | Price | One-liner |\\n|---|---|---|---|\\n| Execute code (Judge0) | Judge0 | $0.005 | `t2000 pay https://mpp.t2000.ai/judge0/v1/submissions --data \'{\\"source_code\\":\\"print(42)\\",\\"language_id\\":71}\'` |\\n| List languages | Judge0 Languages | $0.005 | `t2000 pay https://mpp.t2000.ai/judge0/v1/languages --method GET` |\\n| Shorten URL | Short.io | $0.005 | `t2000 pay https://mpp.t2000.ai/shortio/v1/shorten --data \'{\\"url\\":\\"https://\u2026\\"}\'` |\\n\\n---\\n\\n## How recipes compose\\n\\nThe most common pattern is **chain two paid calls**:\\n\\n```bash\\n# Scrape \u2192 summarize\\nTEXT=$(t2000 pay \u2026/firecrawl/v1/scrape --data \'{\\"url\\":\\"\u2026\\"}\' --json | jq -r \'.data.markdown\')\\nt2000 pay \u2026/openai/v1/chat/completions --data \\"$(jq -nc --arg t \\"$TEXT\\" \'{model:\\"gpt-4o-mini\\",messages:[{role:\\"user\\",content:$t}]}\')\\"\\n\\n# Transcribe \u2192 translate\\nTEXT=$(t2000 pay \u2026/openai/v1/audio/transcriptions --data \'{\\"file\\":\\"\u2026\\"}\' --json | jq -r \'.text\')\\nt2000 pay \u2026/deepl/v1/translate --data \\"$(jq -nc --arg t \\"$TEXT\\" \'{text:[$t],target_lang:\\"ES\\"}\')\\"\\n\\n# Search \u2192 answer\\nHITS=$(t2000 pay \u2026/brave/v1/web/search --data \'{\\"q\\":\\"\u2026\\"}\' --json)\\nt2000 pay \u2026/openai/v1/chat/completions --data \\"$(jq -nc --argjson h \\"$HITS\\" \'{model:\\"gpt-4o\\",messages:[{role:\\"system\\",content:\\"Answer using these sources.\\"},{role:\\"user\\",content:($h|tostring)}]}\')\\"\\n```\\n\\nAlways surface the cumulative cost to the user before kicking off a chain.\\n\\n---\\n\\n## See also\\n\\n- `mpp-image-gen` / `mpp-gpt4o` / `mpp-transcription` \u2014 deep recipes for the 3 most-used services.\\n- `t2000-pay` \u2014 generic technical reference for the `t2000 pay` command (options, flags, errors).\\n- `t2000-services` \u2014 discovers the live service catalog at runtime.\\n- `https://mpp.t2000.ai/llms.txt` \u2014 agent-readable catalog.\\n- `https://mpp.t2000.ai/openapi.json` \u2014 full OpenAPI 3.1 spec."},{"name":"mpp-transcription","description":"Transcribe audio to text via `t2000 pay` against the MPP-protected OpenAI Whisper endpoint at https://mpp.t2000.ai/openai/v1/audio/transcriptions. Use when asked to transcribe a podcast, voice memo, meeting recording, interview, video soundtrack, or any audio \u2192 text task. Pay-per-request (~$0.01 USDC). Accepts a public URL or base64. No API key, no account.","body":"# MPP Recipe: Transcribe Audio\\n\\n## When to use\\n\\nThe user asks for any of:\\n\\n- \\"Transcribe this audio / podcast / meeting / voice memo \u2026\\"\\n- \\"What did they say in this recording?\\"\\n- \\"Convert this voice file to text\\"\\n- \\"Pull a transcript from this MP3/WAV/M4A/MP3 URL\\"\\n\\nFor text \u2192 speech use the `/openai/v1/audio/speech` recipe under `mpp-index`. For speaker-diarized transcripts (who said what) consider AssemblyAI or Fal.ai Whisper in `mpp-index` \u2014 OpenAI Whisper doesn\'t diarize.\\n\\n## Rules\\n\\n1. **Audio must be reachable by a public URL** (or supplied as base64). The gateway can\'t read your local files \u2014 host them first (Vercel Blob, S3, IPFS, Walrus).\\n2. **Whisper handles up to 25 MB / ~30 min.** Longer recordings need to be split client-side. The gateway returns 400 above the limit and you\'re charged.\\n3. **One paid request = one transcription.** No partial / streaming refunds.\\n4. **Pass `language` if you know it.** Auto-detection works but uses a few extra seconds; explicit ISO-639-1 (`en`, `es`, `ja`) is faster and more accurate for short clips.\\n5. **For long-form (podcasts, meetings), AssemblyAI is a better fit** \u2014 set `mpp-index` AssemblyAI ($0.02 + diarization + chapter detection).\\n\\n## The fast path\\n\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/audio/transcriptions \\\\\\n --data \'{\\n \\"file\\": \\"https://example.com/podcast-episode.mp3\\",\\n \\"model\\": \\"whisper-1\\",\\n \\"language\\": \\"en\\"\\n }\'\\n```\\n\\n## Returns\\n\\n```json\\n{\\n \\"text\\": \\"In this episode we discuss the future of agentic finance on Sui...\\"\\n}\\n```\\n\\n**Key field:** `text` \u2014 the full transcript as a single string. No timestamps, no diarization (Whisper doesn\'t do those). For timestamped output use `response_format: \\"verbose_json\\"` (still $0.01).\\n\\n## Tuning knobs\\n\\n| Field | Default | When to set |\\n|---|---|---|\\n| `file` | \u2014 (required) | Public URL to MP3, WAV, M4A, MP4, MPEG, MPGA, WEBM, OGG, or FLAC. \u226425 MB. |\\n| `model` | `whisper-1` | Only option today. Pass it explicitly for clarity. |\\n| `language` | auto-detect | ISO-639-1 code. Always pass when known (faster + more accurate). |\\n| `prompt` | none | Glossary / proper-noun hint string. Useful for jargon-heavy audio: `\\"Sui, NAVI, Cetus, USDC, zkLogin\\"`. |\\n| `response_format` | `json` | Pass `\\"verbose_json\\"` for word-level timestamps. |\\n| `temperature` | `0` | Leave at 0 (deterministic). |\\n\\n## Common patterns\\n\\n**Plain transcript:**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/audio/transcriptions \\\\\\n --data \'{\\"file\\": \\"https://example.com/clip.mp3\\"}\' \\\\\\n | jq -r \'.text\'\\n```\\n\\n**Transcript with timestamps:**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/audio/transcriptions \\\\\\n --data \'{\\n \\"file\\": \\"https://example.com/interview.mp3\\",\\n \\"response_format\\": \\"verbose_json\\",\\n \\"language\\": \\"en\\"\\n }\'\\n```\\n\\nReturns `{ text, segments: [{ start, end, text }, ...] }`.\\n\\n**Transcript with domain vocabulary (DeFi audio):**\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/audio/transcriptions \\\\\\n --data \'{\\n \\"file\\": \\"https://example.com/defi-podcast.mp3\\",\\n \\"language\\": \\"en\\",\\n \\"prompt\\": \\"Sui, NAVI Protocol, Cetus, USDC, USDsui, zkLogin, Enoki, Walrus, Mysten Labs\\"\\n }\'\\n```\\n\\nThe `prompt` field biases Whisper toward known proper nouns. Massively improves accuracy on jargon.\\n\\n**Transcribe \u2192 summarize (two paid calls):**\\n```bash\\n# Step 1: transcribe ($0.01)\\nTRANSCRIPT=$(t2000 pay https://mpp.t2000.ai/openai/v1/audio/transcriptions \\\\\\n --data \'{\\"file\\":\\"https://example.com/meeting.mp3\\",\\"language\\":\\"en\\"}\' \\\\\\n --json | jq -r \'.text\')\\n\\n# Step 2: summarize via GPT-4o ($0.01)\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \\"$(jq -nc --arg t \\"$TRANSCRIPT\\" \'{\\n model: \\"gpt-4o-mini\\",\\n max_tokens: 400,\\n messages: [\\n {role: \\"system\\", content: \\"Summarize this meeting as 5 bullets + action items.\\"},\\n {role: \\"user\\", content: $t}\\n ]\\n }\')\\"\\n```\\n\\nTotal cost: ~$0.02 USDC.\\n\\n**Transcribe + diarize (use AssemblyAI instead):**\\n\\nOpenAI Whisper has no speaker labels. For \\"Speaker 1 said X, Speaker 2 said Y\\" use:\\n\\n```bash\\nt2000 pay https://mpp.t2000.ai/assemblyai/v1/transcribe \\\\\\n --max-price 0.05 \\\\\\n --data \'{\\n \\"audio_url\\": \\"https://example.com/interview.mp3\\",\\n \\"speaker_labels\\": true\\n }\'\\n```\\n\\nTwo-leg flow \u2014 AssemblyAI returns `{ id }`, then poll `/assemblyai/v1/result` ($0.005 each). See `mpp-index` for the full AssemblyAI shape.\\n\\n## Cost guard\\n\\n- **Per-transcription pricing is fixed at $0.01** in MPP, regardless of audio length (within the 25 MB / 30 min limit).\\n- **Default `--max-price`**: `$1.00`. Plenty.\\n- For batch jobs (transcribe a backlog of N episodes), expect `$0.01 \xD7 N`. Surface the total to the user before starting.\\n\\n## Errors\\n\\n- `INSUFFICIENT_BALANCE` \u2014 `t2000 fund` to top up.\\n- `400 invalid_request_error: file is too large` \u2014 split the audio. You\'re charged for failed requests.\\n- `400 invalid_request_error: could not fetch URL` \u2014 make the URL public. The gateway needs `GET` access without auth.\\n- `400 invalid_request_error: file format not supported` \u2014 convert to MP3 or M4A first.\\n\\n## What NOT to do\\n\\n- Don\'t try `file: \\"/path/to/local.mp3\\"`. Whisper needs a URL or base64; local paths don\'t traverse the gateway.\\n- Don\'t transcribe the same audio twice \\"to compare\\" \u2014 Whisper is deterministic at `temperature: 0`.\\n- Don\'t pay AssemblyAI ($0.02) when Whisper ($0.01) is enough \u2014 only diarize when the user needs speaker labels.\\n\\n## Related recipes\\n\\n- `mpp-image-gen` \u2014 generate images via OpenAI.\\n- `mpp-gpt4o` \u2014 chat / summarization after transcription.\\n- `mpp-index` \u2014 AssemblyAI, Fal.ai Whisper, Groq Whisper for alternatives.\\n- `t2000-pay` \u2014 generic `t2000 pay` reference."},{"name":"t2000-account-report","description":"Render a complete account snapshot \u2014 wallet, savings, debt, recent activity, yield, and portfolio allocation, plus a short headline. Use when asked for a full report, account summary, \\"everything about my account\\", or \\"show me the full picture\\". Multi-tool orchestration \u2014 no single CLI command covers all six dimensions.","body":"# t2000: Account Report\\n\\n## Purpose\\nRender a complete account snapshot across six dimensions \u2014 wallet, savings,\\ndebt, recent activity, yield, portfolio allocation \u2014 followed by a 2\u20133\\nsentence headline. This is a **multi-tool orchestration**, not a single CLI\\ncommand. The right call sequence depends on the consumer:\\n\\n| Consumer | Call pattern |\\n|---|---|\\n| **MCP / Cursor / Claude Desktop** | `t2000_overview` covers wallet + savings + debt + health + earnings + rewards in one call. Add `t2000_history` (limit: 20) and `t2000_positions` if you also want activity and per-position APYs. |\\n| **CLI** | `t2000 balance --show-limits` + `t2000 positions` + `t2000 history --limit 20` |\\n| **Engine (audric/web)** | 6 parallel read tools \u2014 one per rendered card (see below). Calling fewer tools = missing cards. |\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent, each read tool renders a\\ncanvas card. **Skipping a tool = missing card.** Always emit all six\\ntool_use blocks in parallel in the same assistant turn:\\n\\n| Tool | Card | Purpose |\\n|---|---|---|\\n| `balance_check` | BALANCE CHECK | Wallet, savings, debt, total |\\n| `savings_info` | SAVINGS INFO | Per-position breakdown, supply/borrow APY, daily earnings |\\n| `health_check` | HEALTH CHECK | Health factor, supplied, borrowed, max borrow, liquidation threshold |\\n| `activity_summary` | ACTIVITY SUMMARY | Monthly tx breakdown by category |\\n| `yield_summary` | YIELD SUMMARY | Today / week / month / all-time earnings, projected yearly |\\n| `portfolio_analysis` | PORTFOLIO ANALYSIS | Allocation %, week change, insights |\\n\\nAfter all six cards render, write a **2\u20133 sentence headline** that:\\n- Leads with net worth and weekly change.\\n- Mentions health factor in one phrase.\\n- Ends with the single most actionable insight (idle USDC, debt repayment, rate gap, etc).\\n- Does **NOT** narrate the cards\' contents \u2014 they render themselves.\\n- Does **NOT** list asset percentages, APYs, or savings positions in prose.\\n\\nMax 3 sentences total.\\n\\n## CLI quick command (no canvas)\\n\\nFor terminal users who just want the numbers in their shell:\\n\\n```bash\\nt2000 balance --show-limits\\nt2000 positions\\nt2000 history --limit 20\\n```\\n\\nThese three commands cover wallet + per-position APYs + recent activity.\\nFor a one-shot machine-parseable version, add `--json` to each.\\n\\n## Notes\\n\\n- This skill orchestrates **read-only** tools \u2014 no signatures, no on-chain writes.\\n- For a workflow-shaped advisor brief on top of this snapshot (recommendations, USDC APY gap, rebalance suggestion), use the `financial-report` MCP prompt \u2014 it composes this skill plus advisor framing.\\n- If the user holds non-USDC tokens, the portfolio card surfaces them but does not flag them as \\"saveable\\" \u2014 see `t2000-save` for the USDC/USDsui save-eligibility rule."},{"name":"t2000-borrow","description":"Borrow USDC or USDsui against savings collateral. Use when asked to borrow, take a loan, get credit, leverage savings, or access funds without withdrawing from savings. A 0.05% protocol fee applies. Only accepts USDC or USDsui. Always validates projected health factor before signing \u2014 refuses if HF would drop below 1.5.","body":"# t2000: Borrow USDC or USDsui\\n\\n## Purpose\\nTake a collateralized loan using savings deposits as collateral.\\nBorrowed funds go to the available balance. A 0.05% protocol fee applies.\\nUSDsui is permitted as a strategic exception (v0.51.0+) alongside USDC \u2014\\nboth have NAVI lending pools.\\n\\n## Rules\\n\\n1. **USDC or USDsui only.** NAVI doesn\'t have lending pools for other tokens. The SDK returns `UNSUPPORTED_ASSET` on anything else.\\n2. **HF \u2265 1.5 is the hard floor.** Refuse the borrow if the projected health factor drops below 1.5; the safeguard layer enforces it. Surface `maxBorrow` from the error and suggest the recovery (repay or add collateral).\\n3. **Always preview HF.** Even when HF stays > 2.0, state the projected HF, borrow amount, and borrow APY before signing. Borrow is the most consequential write \u2014 never silent.\\n4. **Borrow is single-write.** Never bundle with another write in a Payment Intent. The user must consciously accept debt.\\n5. **Repay symmetry is non-negotiable.** A USDsui borrow MUST be repaid with USDsui. If the user only holds USDC, tell them \u2014 do not auto-swap. See `t2000-repay`.\\n6. **Borrow always confirms.** Across every USD-aware permission preset (`conservative` / `balanced` / `aggressive`), `borrow` has `autoBelow: 0` \u2014 it never auto-executes. Treat it as `confirm`-tier under all conditions.\\n\\n## Command\\n```bash\\nt2000 borrow <amount> [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 borrow 40 # 40 USDC (default)\\nt2000 borrow 100 --asset USDsui # 100 USDsui\\n```\\n\\n`--asset` defaults to USDC when omitted.\\n\\n## Pre-borrow safety check (always runs)\\n\\nBefore broadcasting the borrow transaction, t2000 evaluates the projected\\nhealth factor and routes the user through one of three paths:\\n\\n| Projected HF after borrow | What happens |\\n|---|---|\\n| **< 1.5** | **Refuse** \u2014 borrow blocked with `HEALTH_FACTOR_TOO_LOW`. Error includes `maxBorrow` (the largest amount that keeps HF \u2265 1.5). Suggest: repay existing debt OR add more collateral. |\\n| **1.5 \u2013 2.0** | **Warn** \u2014 surface the projected HF and require explicit user confirmation. Always state: borrow amount, projected HF, current borrow APY. Do NOT silently proceed. |\\n| **> 2.0** | **Proceed** \u2014 borrow is well-collateralized, no extra confirmation needed beyond the standard signing flow. |\\n\\nAlways state to the user: **borrow amount**, **interest rate**, and\\n**projected health factor** before signing.\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent:\\n\\n1. Call `health_check` first to get current HF and `maxBorrow`.\\n2. Compute projected HF: `(supplied \xD7 liquidationThreshold) / (borrowed + amountUsd)`.\\n3. Apply the table above \u2014 refuse / warn / proceed.\\n4. On user confirmation, emit `borrow({ amount, asset })` as the write tool_use.\\n\\nBorrows are always **single-write** \u2014 never bundle with another write in a\\nPayment Intent. The user must consciously accept the debt.\\n\\n## Fees\\n\\n- Protocol fee: 0.05% of the borrow amount\\n\\n## Output\\n\\n```\\n\u2713 Borrowed $XX.XX <asset>\\n Health Factor: X.XX\\n Borrow APY: X.XX%\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Error handling\\n\\n- `NO_COLLATERAL` \u2014 no savings deposited to borrow against. Use `t2000 save` first.\\n- `HEALTH_FACTOR_TOO_LOW` \u2014 borrow would drop HF below 1.5. Error data includes `maxBorrow`. Suggest: repay debt or add collateral.\\n- `UNSUPPORTED_ASSET` \u2014 asset is not USDC or USDsui. Other tokens cannot be borrowed (NAVI doesn\'t have pools for them).\\n\\n## Repayment symmetry (important)\\n\\n**A USDsui borrow MUST be repaid with USDsui.** A USDC borrow MUST be repaid\\nwith USDC. The SDK fetches the matching coin type per borrow asset. If the\\nuser holds only the wrong stable, tell them to swap manually first \u2014 never\\nauto-chain swap + repay. See `t2000-repay` for the repay flow.\\n\\n## What\'s NOT permitted\\n\\n- Borrowing in any asset other than USDC or USDsui (no SUI, GOLD, USDT, ETH borrows \u2014 NAVI doesn\'t have lending pools for those).\\n- Borrowing without a savings position (collateral first).\\n- Borrowing that drops HF below 1.5 (always refused; safety-critical)."},{"name":"t2000-check-balance","description":"Check the t2000 agent wallet balance on Sui. Use when asked about wallet balance, how much USDC is available, savings balance, gas reserve, or total funds. Also use before any send or borrow operation to confirm sufficient funds exist.","body":"# t2000: Check Balance\\n\\n## Purpose\\nFetch the current balance across all accounts: available USDC,\\nsavings (NAVI), gas reserve (SUI), and total value.\\n\\n## Commands\\n```bash\\nt2000 balance # human-readable summary\\nt2000 balance --show-limits # includes maxWithdraw, maxBorrow, healthFactor\\nt2000 balance --json # machine-parseable JSON (works on all commands)\\n```\\n\\n## Output (default)\\n```\\nAvailable: $150.00 (checking \u2014 spendable)\\nSavings: $2,000.00 (earning 5.10% APY)\\nGas: 0.50 SUI (~$0.50)\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\nTotal: $2,150.50\\nEarning ~$0.27/day\\n```\\n\\n## Output (--show-limits)\\nAppends to the above:\\n```\\nLimits:\\n Max withdraw: $XX.XX\\n Max borrow: $XX.XX\\n Health factor: X.XX (\u221E if no active loan)\\n```\\n\\n## Notes\\n- `gasReserve.usdEquiv` is an estimate at current SUI price; it fluctuates\\n- If balance shows $0.00 available and wallet was just created, fund it first\\n via Coinbase Onramp or a direct USDC transfer to the wallet address\\n- `--json` is a global flag that works on all t2000 commands, not just balance"},{"name":"t2000-contacts","description":"Manage contacts \u2014 save a name-to-address mapping so the user can send money by name instead of pasting raw Sui addresses. Use when asked to add, remove, or list contacts, or to look up a saved address.","body":"# t2000: Contacts\\n\\n## Purpose\\nLet users send money by name instead of raw addresses. Contacts are stored\\nlocally in `~/.t2000/contacts.json` \u2014 no blockchain lookups, no network calls.\\n\\n## Commands\\n\\n```bash\\n# List all contacts\\nt2000 contacts\\n\\n# Add or update a contact\\nt2000 contacts add <name> <address>\\n\\n# Remove a contact\\nt2000 contacts remove <name>\\n```\\n\\n## Examples\\n\\n```bash\\nt2000 contacts add Tom 0x8b3e4f2a...\\n# \u2713 Added Tom (0x8b3e...f4a2)\\n\\nt2000 contacts add Tom 0xNEWADDRESS...\\n# \u2713 Updated Tom (0xNEWA...RESS)\\n\\nt2000 contacts remove Tom\\n# \u2713 Removed Tom\\n\\nt2000 contacts\\n# Contacts\\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n# Tom 0x8b3e...f4a2\\n# Alice 0x40cd...3e62\\n```\\n\\n## Sending by name\\n\\nOnce a contact is saved, use the name directly in `t2000 send`:\\n\\n```bash\\nt2000 send 50 USDC to Tom\\n# \u2713 Sent $50.00 USDC \u2192 Tom (0x8b3e...f4a2)\\n```\\n\\n## Name rules\\n- Letters, numbers, underscores only\\n- Case-insensitive (Tom = tom = TOM)\\n- Max 32 characters\\n- Reserved names: `to`, `all`, `address`\\n- Cannot start with `0x`\\n\\n## No PIN required\\nContact commands are local file operations \u2014 no wallet access, no PIN prompt.\\n\\n## JSON mode\\nAll subcommands support `--json` for structured output:\\n\\n```bash\\nt2000 contacts --json\\nt2000 contacts add Tom 0x... --json\\nt2000 contacts remove Tom --json\\n```\\n\\n## Error handling\\n- `INVALID_CONTACT_NAME`: name violates naming rules\\n- `CONTACT_NOT_FOUND`: name not in contacts when sending\\n- `INVALID_ADDRESS`: address provided to `add` is not a valid Sui address"},{"name":"t2000-engine","description":"Use the @t2000/engine package to build conversational AI agents with financial capabilities. Use when asked to set up AISDKEngine, build custom tools, configure LLM providers, handle streaming events, or integrate with MCP servers. Powers the Audric consumer product.","body":"# t2000: Agent Engine\\n\\n## Purpose\\nBuild conversational AI agents with financial capabilities on Sui.\\n`@t2000/engine` provides `AISDKEngine`, 26 financial tools (18 read + 8 write),\\nLLM orchestration via Vercel AI SDK v6, MCP client/server integration,\\nstreaming, sessions, and cost tracking.\\n\\n> The legacy `QueryEngine` + `AnthropicProvider` were deleted in engine v2.0.0 (2026-05-17).\\n> The `LLMProvider` abstraction + `AISDKAnthropicProvider` class were retired in v3.1.0\\n> (2026-05-25). `AISDKEngine` is the only engine; it wraps Vercel AI SDK v6\'s `streamText`\\n> and accepts `anthropicApiKey` (or `modelInstance` for custom providers / gateway routing).\\n\\n## Quick Start\\n```typescript\\nimport { AISDKEngine, getDefaultTools } from \'@t2000/engine\';\\nimport { T2000 } from \'@t2000/sdk\';\\n\\nconst agent = await T2000.create({ pin: process.env.T2000_PIN });\\n\\nconst engine = new AISDKEngine({\\n anthropicApiKey: process.env.ANTHROPIC_API_KEY,\\n agent,\\n tools: getDefaultTools(),\\n});\\n\\nfor await (const event of engine.submitMessage(\'What is my balance?\')) {\\n if (event.type === \'text_delta\') process.stdout.write(event.text);\\n}\\n```\\n\\n## Building Custom Tools\\n```typescript\\nimport { z } from \'zod\';\\nimport { defineTool } from \'@t2000/engine\';\\n\\nconst myTool = defineTool({\\n name: \'my_tool\',\\n description: \'Tool description for the LLM\',\\n inputSchema: z.object({ query: z.string() }),\\n isReadOnly: true,\\n isConcurrencySafe: true,\\n permissionLevel: \'auto\',\\n async call(input, context) {\\n return { data: { result: input.query }, displayText: `Result: ${input.query}` };\\n },\\n});\\n```\\n\\n> `defineTool` is the v2 factory. The pre-v2 `buildTool` was deleted in engine\\n> `1.38.0`. Signature is the same (Zod schema, isReadOnly, permissionLevel, `call`).\\n\\n## Permission Levels\\n| Level | Behavior | Use for |\\n|-------|----------|---------|\\n| `auto` | Executes immediately | Read-only queries |\\n| `confirm` | Yields `pending_action`, client executes and resumes | Financial writes |\\n| `explicit` | Never auto-dispatched by LLM | Dangerous operations |\\n\\nUSD-aware resolution: write tools with `permissionLevel: \'confirm\'` are\\ndynamically downgraded to `auto` if `amountUsd < rule.autoBelow` and the user\'s\\n`permissionConfig` is plumbed through `ToolContext`. See\\n`packages/engine/src/permission-rules.ts` for the three presets\\n(`conservative` / `balanced` / `aggressive`) and `borrow`-always-confirms rule.\\n\\n## Event Types\\n```typescript\\nfor await (const event of engine.submitMessage(prompt)) {\\n switch (event.type) {\\n case \'stream_started\': // first event \u2014 carries engine-generated streamId (v2.2.0+, when streamCheckpointStore is wired)\\n case \'text_delta\': // LLM text chunk (markers like <proactive> and <eval_summary> pass through verbatim; host strips at render)\\n case \'thinking_delta\': // Extended-thinking chunk (always-on)\\n case \'thinking_done\': // Thinking block closed\\n case \'tool_start\': // Tool execution beginning\\n case \'tool_result\': // Tool execution complete\\n case \'pending_action\': // Write tool needs approval \u2192 client executes, then resumes. action.attemptId is a UUID v4; persist on TurnMetrics + key resume `updateMany` on it\\n case \'canvas\': // Inline HTML/React canvas artifact\\n case \'turn_complete\': // Conversation turn finished\\n case \'usage\': // Token usage report (input / output / cache reads + writes)\\n case \'error\': // Unrecoverable error\\n }\\n}\\n```\\n\\n## MCP Client (consume external MCPs)\\n```typescript\\nimport { McpClientManager, NAVI_MCP_CONFIG } from \'@t2000/engine\';\\n\\nconst mcpManager = new McpClientManager();\\nawait mcpManager.connect(NAVI_MCP_CONFIG);\\n\\n// Read tools auto-use MCP when available, SDK as fallback\\nconst engine = new AISDKEngine({\\n provider,\\n agent,\\n mcpManager,\\n walletAddress: \'0x...\',\\n tools: getDefaultTools(),\\n});\\n```\\n\\n> Internally backed by `@ai-sdk/mcp`\'s `createMCPClient` since engine `v2.1.0`\\n> (SPEC 37 v0.7a Phase 4); `McpClientManager` class name + public method\\n> signatures preserved verbatim. `McpPromptAdapter` for MCP prompts is new in `v2.1.0`.\\n\\n## MCP Server (expose tools to AI clients)\\n```typescript\\nimport { registerEngineTools, getDefaultTools } from \'@t2000/engine\';\\nimport { McpServer } from \'@modelcontextprotocol/sdk/server/mcp.js\';\\n\\nconst server = new McpServer({ name: \'audric\', version: \'0.1.0\' });\\nregisterEngineTools(server, getDefaultTools());\\n// Tools exposed as audric_balance_check, audric_save_deposit, etc.\\n```\\n\\n## SSE Streaming (web apps)\\n```typescript\\n// [v2.2.0 / SPEC 37 v0.7a Phase 5 Slice A] `engineToSSE` was deleted \u2014\\n// iterate EngineEvent raw and call serializeSSE per event. Audric chat +\\n// resume routes have used this pattern since v1.4.2 (Spec G3). Hosts that\\n// want the SPEC 21.1 routing/quoting/etc \u2192 stream_state choreography wrap\\n// with `withStreamState` directly.\\nimport { serializeSSE, withStreamState } from \'@t2000/engine\';\\n\\nfor await (const event of withStreamState(engine.submitMessage(prompt))) {\\n const wireBytes = event.type === \'error\'\\n ? serializeSSE({ type: \'error\', message: event.error.message })\\n : serializeSSE(event);\\n // Send wireBytes to client via SSE\\n}\\n// Write tools yield pending_action \u2192 client executes on-chain \u2192 POST /api/engine/resume\\n```\\n\\n## Stream Checkpoint Resume (v2.2.0+)\\n```typescript\\n// Wire a checkpoint store to enable page-reload / cold-start resume of the\\n// LIVE stream. Engine emits `stream_started` first (carries the streamId),\\n// appends every event fire-and-forget, and replays the checkpoint when the\\n// host passes the id back as `EngineConfig.resumeStreamId`.\\nimport { InMemoryStreamCheckpointStore } from \'@t2000/engine\';\\n\\nconst engine = new AISDKEngine({\\n // ...\\n streamCheckpointStore: new InMemoryStreamCheckpointStore(),\\n});\\n// In-flight tool on resume = Path B (error + re-prompt). CLI / MCP / tests\\n// use the in-memory default; multi-instance hosts (audric on Vercel) inject Upstash.\\n```\\n\\n## Built-in Tools (26 \u2014 was 31 pre-S.277)\\n\\n### Read (18, parallel, auto-approved)\\n`render_canvas`, `balance_check`, `savings_info`, `health_check`, `rates_info`,\\n`transaction_history`, `swap_quote`, `explain_tx`, `portfolio_analysis`,\\n`token_prices`, `create_payment_link`, `list_payment_links`,\\n`cancel_payment_link`, `spending_analytics`, `yield_summary`,\\n`activity_summary`, `resolve_suins`, `pending_rewards`\\n\\n### Write (8, structurally serial, confirmation required)\\n`save_deposit` (USDC + USDsui), `withdraw`, `send_transfer`,\\n`borrow` (USDC + USDsui), `repay_debt` (USDC + USDsui \u2014 same asset as borrow),\\n`claim_rewards`, `harvest_rewards`, `swap_execute`\\n\\n> **S.245 (2026-05-22):** `pay_api` (write) + `mpp_services` (read) deleted\\n> per V07E_D_QUESTION_AUDITS D-2 reframe. The legacy MPP gateway\\n> capability returns as a Commerce primitive in the upcoming Audric Store\\n> SPEC \u2014 clean-slate redesign, not a port of the legacy 3-leg apps/web flow.\\n>\\n> **S.269 (2026-05-23):** `save_contact` deleted (engine-side dead \u2014 host\\n> owns Prisma persistence). V07E_INVOICE_DEPRECATION (item 7 of S.269)\\n> deleted 3 invoice tools \u2014 `create_invoice`, `list_invoices`,\\n> `cancel_invoice` \u2014 and the `InvoiceSchema` Zod definition. Payment\\n> links absorb the invoicing use case (label/memo encode invoice\\n> context). 35 \u2192 31 tools.\\n>\\n> **S.277 (2026-05-23):** \\"Earns Its Keep\\" audit cut 5 tools + 2 dead\\n> guards (engine 2.18.0). Volo trio (`volo_stats`, `volo_stake`,\\n> `volo_unstake`) \u2014 no Audric chip / product slot for liquid staking;\\n> `harvest_rewards` routes vSUI via Cetus, not Volo. `web_search`\\n> (Brave-backed) \u2014 gateway path uses Vercel AI Gateway\'s\\n> `perplexity_search` instead. `protocol_deep_dive` (DefiLlama) \u2014\\n> `rates_info` covers the in-product safety lens; engine no longer\\n> talks to `api.llama.fi`. 2 dead guards removed (`guardCostWarning`,\\n> `guardArtifactPreview`) \u2014 both unreachable post-S.245. `explain_tx`\\n> kept but description tightened to \\"arbitrary external digest only\\".\\n> (Pre-S.323: SDK + CLI + MCP retained Volo for non-Audric consumers;\\n> S.323 cut those too.) 31 \u2192 26 tools (18 read + 8 write), 14 \u2192 12 guards.\\n>\\n> **S.323 (2026-05-25):** Volo fully removed across SDK + CLI + MCP. vSUI\\n> remains as a passive token (NAVI reward, Cetus swap target), but\\n> `agent.stakeVSui` / `t2000 stake` / `t2000_stake` are gone. Engine\\n> surface unchanged from S.277.\\n>\\n> **S.269 item 6 (2026-05-23):** `save_contact` (write) deleted as part of\\n> the template-divergence cleanup slice. Engine-side dead tool \u2014 host-side\\n> Prisma persistence with no engine-owned effect; the user surface is the\\n> audric send screen, not the LLM.\\n>\\n> **S.277 (2026-05-23):** \\"Earns Its Keep\\" audit cut 5 tools from the\\n> engine surface \u2014 `volo_stats` / `volo_stake` / `volo_unstake` (no\\n> Audric chip / product slot; SDK + CLI + MCP retained Volo at the time\\n> for non-Audric consumers, until full removal in S.323),\\n> `web_search` (Brave-backed; gateway path uses Vercel AI Gateway\'s\\n> `perplexity_search`), `protocol_deep_dive` (DefiLlama-backed;\\n> rates_info is the in-product proxy). Also dropped: 2 dead guards\\n> (`costWarning`, `artifactPreview`) + the `costAware` flag. `explain_tx`\\n> kept but description tightened to \\"arbitrary external digest only\\". Net\\n> 31 \u2192 26 engine tools. See `spec/archive/v07e/AUDIT_V07E_EARNS_ITS_KEEP_2026-05-23.md`.\\n\\n> Write serialization is structural in v2 \u2014 no in-process mutex. Confirm-tier\\n> writes yield a `pending_action` event, the host round-trips through user\\n> confirm, and the next step runs the next write. Auto-execute writes\\n> (USD-aware permission resolver, sub-threshold) inherit one-write-per-step\\n> from the LLM\'s planning + the conservative-default preset.\\n\\n## Configuration\\n```typescript\\nnew AISDKEngine({\\n anthropicApiKey: process.env.ANTHROPIC_API_KEY, // Required (or pass `modelInstance` for custom providers)\\n agent, // T2000 SDK instance\\n mcpManager, // McpClientManager for MCP-first reads\\n walletAddress, // Sui address for MCP reads\\n tools: getDefaultTools(),\\n systemPrompt, // Override default Audric prompt\\n model: \'claude-sonnet-4-5\',\\n maxTurns: 10,\\n maxTokens: 4096,\\n costTracker: { budgetLimitUsd: 1.0 },\\n streamCheckpointStore, // optional, v2.2.0+ for live-stream resume\\n resumeStreamId, // optional, replays a checkpointed stream on cold start\\n});\\n```\\n\\n## Key Imports\\n```typescript\\n// Core\\nimport { AISDKEngine, getDefaultTools } from \'@t2000/engine\';\\n// Tools (defineTool is the v2 factory; READ_TOOL_SET / WRITE_TOOL_SET / READ_TOOL_NAMES are the tool registries since v3.0.0)\\nimport { defineTool, READ_TOOL_SET, WRITE_TOOL_SET, READ_TOOL_NAMES } from \'@t2000/engine\';\\n// Streaming (`engineToSSE` was deleted in v2.2.0 \u2014 see \\"SSE Streaming\\" above)\\nimport { serializeSSE, parseSSE, withStreamState } from \'@t2000/engine\';\\n// Stream checkpoint resume (v2.2.0+)\\nimport { InMemoryStreamCheckpointStore } from \'@t2000/engine\';\\n// Sessions\\nimport { MemorySessionStore } from \'@t2000/engine\';\\n// Cost\\nimport { CostTracker } from \'@t2000/engine\';\\n// Microcompact + context budgeting\\nimport { microcompact, compactMessages, estimateTokens } from \'@t2000/engine\';\\n// Granular permissions (USD-aware resolver)\\nimport {\\n resolvePermissionTier, resolveUsdValue, toolNameToOperation,\\n DEFAULT_PERMISSION_CONFIG, PERMISSION_PRESETS,\\n} from \'@t2000/engine\';\\n// MCP\\nimport {\\n McpClientManager, McpPromptAdapter,\\n NAVI_MCP_CONFIG, buildMcpTools, registerEngineTools,\\n} from \'@t2000/engine\';\\n```"},{"name":"t2000-mcp","description":"Connect a t2000 Agentic Wallet to Claude Desktop, Cursor, Cline, Continue, or any MCP-compatible client. Use when asked to set up MCP, paste an MCP server config, install @t2000/mcp, or troubleshoot why the MCP server \\"doesn\'t do anything\\" when run from a terminal. Provides 27 tools and 35 prompts (14 workflow + 21 skill) over stdio.","body":"# t2000: MCP Server\\n\\n## Purpose\\nExpose a t2000 Agentic Wallet (Sui wallet + DeFi positions) to any\\nMCP-compatible AI client over stdio. **27 tools, 35 prompts** (14 workflow\\nprompts + 21 skill prompts auto-derived from `t2000-skills/skills/`),\\nsafeguard enforced. No global install required \u2014 the recommended path\\nuses `npx` so the AI client always pulls the latest published version.\\n\\n## \u26A0\uFE0F The most common confusion\\n\\n**`npx @t2000/mcp` is NOT a command you run from a terminal to \\"use\\" the\\nMCP server.** It is a JSON-RPC server that listens silently on `stdin`.\\nIf you run it manually it will appear to hang \u2014 that\'s correct behavior.\\nIt is meant to be launched as a subprocess by an AI client (Claude\\nDesktop, Cursor, etc.) which speaks JSON-RPC to it over `stdin`/`stdout`.\\n\\nThe JSON snippets below go into your **AI client\'s MCP settings file**,\\nnot into a shell.\\n\\n## Setup\\n\\n### 1. Create a wallet + safeguards (one-time, in a terminal)\\n\\n```bash\\n# Install CLI long enough to bootstrap a wallet and set safety limits\\nnpx @t2000/cli init\\nnpx @t2000/cli config set maxPerTx 100\\nnpx @t2000/cli config set maxDailySend 500\\n\\n# Create a session so MCP can reuse the saved PIN\\nnpx @t2000/cli balance\\n```\\n\\nThe MCP server **refuses to start** until `maxPerTx` and `maxDailySend`\\nare configured. This is intentional.\\n\\n### 2. Add the MCP server to your AI client\\n\\nRecommended config (auto-updates on every launch, no global install):\\n\\n```json\\n{\\n \\"mcpServers\\": {\\n \\"t2000\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"-y\\", \\"@t2000/mcp@latest\\"]\\n }\\n }\\n}\\n```\\n\\nAlternative (if `@t2000/cli` is already installed globally):\\n\\n```json\\n{\\n \\"mcpServers\\": {\\n \\"t2000\\": {\\n \\"command\\": \\"t2000\\",\\n \\"args\\": [\\"mcp\\"]\\n }\\n }\\n}\\n```\\n\\n### 3. Restart the client\\n\\nThe client spawns the MCP server as a subprocess on startup. You should\\nsee `t2000_*` tools appear in the tool list.\\n\\n## Per-client config file paths\\n\\n| Client | Config file |\\n|--------|-------------|\\n| Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |\\n| Claude Desktop (Windows) | `%APPDATA%\\\\Claude\\\\claude_desktop_config.json` |\\n| Cursor | Settings \u2192 MCP \u2192 Add new MCP server (or `~/.cursor/mcp.json`) |\\n| Cline | VSCode settings \u2192 `cline.mcpServers` |\\n| Continue | `~/.continue/config.json` under `mcpServers` |\\n\\n## Verification (optional, before wiring into a client)\\n\\nConfirm the server responds to a real MCP `initialize` request:\\n\\n```bash\\nprintf \'%s\\\\n\' \\\\\\n \'{\\"jsonrpc\\":\\"2.0\\",\\"id\\":1,\\"method\\":\\"initialize\\",\\"params\\":{\\"protocolVersion\\":\\"2024-11-05\\",\\"capabilities\\":{},\\"clientInfo\\":{\\"name\\":\\"test\\",\\"version\\":\\"1.0\\"}}}\' \\\\\\n | npx -y @t2000/mcp@latest\\n```\\n\\nYou should see a JSON response containing `\\"serverInfo\\":{\\"name\\":\\"t2000\\"...}`\\nand exit. If you see that, the server is healthy and ready to be launched\\nby a client.\\n\\n## Available Tools (27)\\n\\n### Read-only (15)\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_overview` | Complete account snapshot in one call |\\n| `t2000_balance` | Current balance |\\n| `t2000_address` | Wallet address |\\n| `t2000_positions` | Lending positions |\\n| `t2000_rates` | Best interest rates per asset |\\n| `t2000_all_rates` | Per-protocol rate comparison |\\n| `t2000_health` | Health factor |\\n| `t2000_history` | Transaction history |\\n| `t2000_earnings` | Yield earnings |\\n| `t2000_fund_status` | Savings fund status |\\n| `t2000_pending_rewards` | Pending protocol rewards |\\n| `t2000_deposit_info` | Deposit instructions |\\n| `t2000_receive` | Generate payment request with address, nonce, and Payment Kit URI (`sui:pay?\u2026`) |\\n| `t2000_services` | List all MPP services and endpoints |\\n| `t2000_contacts` | List saved contacts |\\n\\n### State-changing (10)\\nAll support `dryRun: true` for previews without signing.\\n\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_send` | Send USDC |\\n| `t2000_save` | Deposit to savings |\\n| `t2000_withdraw` | Withdraw from savings |\\n| `t2000_borrow` | Borrow against collateral |\\n| `t2000_repay` | Repay debt |\\n| `t2000_claim_rewards` | Claim pending protocol rewards |\\n| `t2000_pay` | Pay for and call any MPP API service with USDC |\\n| `t2000_swap` | Execute a token swap via Cetus Aggregator |\\n| `t2000_contact_add` | Save a contact name \u2192 address |\\n| `t2000_contact_remove` | Remove a saved contact |\\n\\n> **S.323 (2026-05-25):** `t2000_stake` + `t2000_unstake` removed (full Volo cut across SDK + CLI + MCP). vSUI remains as a tradeable token via `t2000_swap`, but there is no longer a way to mint / redeem vSUI through t2000.\\n\\n### Safety (2)\\n| Tool | Description |\\n|------|-------------|\\n| `t2000_config` | View/set limits |\\n| `t2000_lock` | Emergency freeze |\\n\\n## Prompts (31 total)\\n\\nThe MCP server exposes TWO classes of prompts. Both appear in the AI client\'s `/` prompt picker after restart.\\n\\n### Workflow prompts (14) \u2014 multi-skill orchestrations\\n\\n| Prompt | Description |\\n|--------|-------------|\\n| `financial-report` | Full financial summary |\\n| `optimize-yield` | Yield optimization analysis |\\n| `send-money` | Guided send with preview |\\n| `budget-check` | Can I afford $X? |\\n| `savings-strategy` | Recommend how much to save and where |\\n| `what-if` | Scenario planning \u2014 model impact before acting |\\n| `sweep` | Route idle funds to optimal earning positions |\\n| `risk-check` | Health factor, concentration, liquidation risk |\\n| `weekly-recap` | Week in review \u2014 activity, yield |\\n| `claim-rewards` | Check and claim pending protocol rewards |\\n| `safeguards` | Review safety settings \u2014 limits, lock, PIN-protected operations |\\n| `onboarding` | New user setup \u2014 deposit, first save, explore features |\\n| `emergency` | Lock account, assess damage, recovery guidance |\\n| `optimize-all` | One-shot full optimization \u2014 sweep, compare APYs, claim rewards |\\n\\n### Skill prompts (21) \u2014 auto-derived from `t2000-skills/skills/`\\n\\nEvery `SKILL.md` in `t2000-skills/skills/` is registered at server startup as a prompt named `skill-<short-name>` (the `t2000-` prefix is stripped; other prefixes like `mpp-` are preserved for disambiguation). Invoking the prompt loads the full skill markdown as the user message \u2014 equivalent to the agent reading the skill from `t2000.ai/skills/<slug>`.\\n\\n#### Core wallet skills (17)\\n\\n| Prompt | Maps to |\\n|--------|---------|\\n| `skill-setup` | `t2000-setup` \u2014 one-prompt install entry point |\\n| `skill-check-balance` | `t2000-check-balance` |\\n| `skill-send` | `t2000-send` |\\n| `skill-receive` | `t2000-receive` |\\n| `skill-save` | `t2000-save` |\\n| `skill-withdraw` | `t2000-withdraw` |\\n| `skill-borrow` | `t2000-borrow` |\\n| `skill-repay` | `t2000-repay` |\\n| `skill-swap` | `t2000-swap` |\\n| `skill-yields` | `t2000-yields` |\\n| `skill-pay` | `t2000-pay` |\\n| `skill-contacts` | `t2000-contacts` |\\n| `skill-safeguards` | `t2000-safeguards` |\\n| `skill-account-report` | `t2000-account-report` |\\n| `skill-rebalance` | `t2000-rebalance` |\\n| `skill-mcp` | `t2000-mcp` (this skill) |\\n| `skill-engine` | `t2000-engine` |\\n\\n#### MPP recipes (4)\\n\\n| Prompt | Maps to |\\n|--------|---------|\\n| `skill-mpp-image-gen` | `mpp-image-gen` \u2014 OpenAI gpt-image-1 ($0.05) |\\n| `skill-mpp-gpt4o` | `mpp-gpt4o` \u2014 OpenAI chat completions ($0.01) |\\n| `skill-mpp-transcription` | `mpp-transcription` \u2014 OpenAI Whisper ($0.01) |\\n| `skill-mpp-index` | `mpp-index` \u2014 intent-grouped discovery for all 40 MPP services |\\n\\nThis is the canonical way to surface t2000 skills inside an MCP-aware AI client \u2014 no separate skill install needed. Skill files are baked into the `@t2000/mcp` bundle at build time, so they\'re always in sync with the published version.\\n\\n## Troubleshooting\\n\\n| Symptom | Cause | Fix |\\n|---------|-------|-----|\\n| `npx @t2000/mcp` \\"hangs\\" with no output | Working as designed \u2014 server is waiting for JSON-RPC on stdin | Don\'t run it manually; let the AI client launch it |\\n| Server exits with `Safeguards not configured` | `maxPerTx` / `maxDailySend` not set | Run `npx @t2000/cli config set maxPerTx 100 && ... maxDailySend 500` |\\n| Client shows no `t2000_*` tools after restart | Wrong config path, or stale npx cache | Verify with the `printf | npx ...` test above; clear cache with `rm -rf ~/.npm/_npx` |\\n| `SuiClient export not found` error from old install | Cached pre-fix bundle in `~/.npm/_npx` | `rm -rf ~/.npm/_npx` then restart the client |\\n\\n## Engine MCP Adapter (Audric)\\n\\n`@t2000/engine` can also expose its financial tools as MCP tools, enabling\\nAudric to serve as an MCP server alongside `@t2000/mcp`:\\n\\n```typescript\\nimport { registerEngineTools, getDefaultTools } from \'@t2000/engine\';\\nimport { McpServer } from \'@modelcontextprotocol/sdk/server/mcp.js\';\\n\\nconst server = new McpServer({ name: \'audric\', version: \'0.1.0\' });\\nregisterEngineTools(server, getDefaultTools());\\n// Exposes: audric_balance_check, audric_save_deposit, etc.\\n```\\n\\nEngine tools use `audric_` prefix to avoid collisions with `t2000_` prefixed\\ntools from `@t2000/mcp`. The engine adapter includes permission-level metadata\\nand supports the full confirmation flow.\\n\\n## Security\\n- Safeguard gate: server refuses to start without configured limits\\n- `unlock` is CLI-only \u2014 AI cannot circumvent a locked agent\\n- `dryRun: true` previews operations before signing\\n- Local-only stdio transport \u2014 key never leaves the machine"},{"name":"t2000-pay","description":"Pay for an MPP-protected API service using the t2000 wallet. Use when asked to call an AI model, search the web, generate images, send email, buy gift cards, send physical mail, check weather, execute code, or any task that requires a paid API. Handles the full MPP 402 challenge automatically. Use t2000_services to discover all available services first.","body":"# t2000: Pay for MPP API Service\\n\\n## Status\\nActive \u2014 requires `t2000` CLI with `@suimpp/mpp` installed.\\n\\n## Purpose\\nMake a paid HTTP request to any MPP-protected endpoint. Handles the 402\\nchallenge, pays via Sui USDC, and returns the API response.\\n\\n## Service Discovery\\nBefore calling `t2000 pay`, discover available services:\\n```bash\\n# CLI\\nt2000 pay https://mpp.t2000.ai/api/services\\n\\n# MCP\\nt2000_services\\n```\\n\\nAll services are hosted at `https://mpp.t2000.ai/`.\\n\\n## Command\\n```bash\\nt2000 pay <url> [options]\\n```\\n\\n## Options\\n| Option | Description | Default |\\n|--------|-------------|---------|\\n| `--method <method>` | HTTP method (GET, POST, PUT) | POST |\\n| `--data <json>` | Request body for POST/PUT | \u2014 |\\n| `--max-price <amount>` | Max USDC per request | $1.00 |\\n| `--header <key=value>` | Additional HTTP header (repeatable) | \u2014 |\\n| `--timeout <seconds>` | Request timeout in seconds | 30 |\\n| `--dry-run` | Show what would be paid without paying | \u2014 |\\n\\n## Available Services (40 services, 88 endpoints)\\n\\n> For the live, canonical list use `t2000_services` (MCP) or GET `https://mpp.t2000.ai/api/services`.\\n> The table below is a quick reference.\\n\\n### AI Models\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenAI Chat | `/openai/v1/chat/completions` | $0.01 |\\n| OpenAI Embeddings | `/openai/v1/embeddings` | $0.005 |\\n| OpenAI Audio Transcription | `/openai/v1/audio/transcriptions` | $0.01 |\\n| OpenAI Text-to-Speech | `/openai/v1/audio/speech` | $0.02 |\\n| Anthropic | `/anthropic/v1/messages` | $0.01 |\\n| Google Gemini Flash | `/gemini/v1beta/models/gemini-2.5-flash` | $0.005 |\\n| Google Gemini Pro | `/gemini/v1beta/models/gemini-2.5-pro` | $0.01 |\\n| Google Gemini Embeddings | `/gemini/v1beta/models/embedding-001` | $0.005 |\\n| DeepSeek | `/deepseek/v1/chat/completions` | $0.005 |\\n| Groq Chat | `/groq/v1/chat/completions` | $0.005 |\\n| Groq Audio Transcription | `/groq/v1/audio/transcriptions` | $0.005 |\\n| Together AI Chat | `/together/v1/chat/completions` | $0.005 |\\n| Together AI Embeddings | `/together/v1/embeddings` | $0.005 |\\n| Perplexity | `/perplexity/v1/chat/completions` | $0.01 |\\n| Mistral Chat | `/mistral/v1/chat/completions` | $0.005 |\\n| Mistral Embeddings | `/mistral/v1/embeddings` | $0.005 |\\n| Cohere Chat | `/cohere/v1/chat` | $0.005 |\\n| Cohere Embed | `/cohere/v1/embed` | $0.005 |\\n| Cohere Rerank | `/cohere/v1/rerank` | $0.005 |\\n\\n### Media & Generation\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenAI DALL-E | `/openai/v1/images/generations` | $0.05 |\\n| Fal.ai Flux Dev | `/fal/fal-ai/flux/dev` | $0.03 |\\n| Fal.ai Flux Pro | `/fal/fal-ai/flux-pro` | $0.05 |\\n| Fal.ai Flux Realism | `/fal/fal-ai/flux-realism` | $0.05 |\\n| Fal.ai Recraft 20B | `/fal/fal-ai/recraft-20b` | $0.05 |\\n| Fal.ai Whisper | `/fal/fal-ai/whisper` | $0.01 |\\n| Together AI Images | `/together/v1/images/generations` | $0.03 |\\n| ElevenLabs TTS | `/elevenlabs/v1/text-to-speech/:voiceId` | $0.05 |\\n| ElevenLabs SFX | `/elevenlabs/v1/sound-generation` | $0.05 |\\n| Replicate (any model) | `/replicate/v1/predictions` | $0.02 |\\n| Replicate (check status) | `/replicate/v1/predictions/status` | $0.005 |\\n| Stability AI (generate) | `/stability/v1/generate` | $0.03 |\\n| Stability AI (edit) | `/stability/v1/edit` | $0.03 |\\n| AssemblyAI (transcribe) | `/assemblyai/v1/transcribe` | $0.02 |\\n| AssemblyAI (get result) | `/assemblyai/v1/result` | $0.005 |\\n\\n### Search\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Brave Web Search | `/brave/v1/web/search` | $0.005 |\\n| Brave Image Search | `/brave/v1/images/search` | $0.005 |\\n| Brave News Search | `/brave/v1/news/search` | $0.005 |\\n| Brave Video Search | `/brave/v1/videos/search` | $0.005 |\\n| Brave Summarizer | `/brave/v1/summarizer/search` | $0.01 |\\n| Exa (semantic search) | `/exa/v1/search` | $0.01 |\\n| Exa (content extract) | `/exa/v1/contents` | $0.01 |\\n| Serper (Google search) | `/serper/v1/search` | $0.005 |\\n| Serper (image search) | `/serper/v1/images` | $0.005 |\\n| SerpAPI (Google search) | `/serpapi/v1/search` | $0.01 |\\n| SerpAPI (Google Flights) | `/serpapi/v1/flights` | $0.01 |\\n| SerpAPI (locations) | `/serpapi/v1/locations` | $0.005 |\\n| NewsAPI (headlines) | `/newsapi/v1/headlines` | $0.005 |\\n| NewsAPI (article search) | `/newsapi/v1/search` | $0.005 |\\n\\n### Data\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| OpenWeather Current | `/openweather/v1/weather` | $0.005 |\\n| OpenWeather Forecast | `/openweather/v1/forecast` | $0.005 |\\n| Google Maps Geocode | `/googlemaps/v1/geocode` | $0.01 |\\n| Google Maps Places | `/googlemaps/v1/places` | $0.01 |\\n| Google Maps Directions | `/googlemaps/v1/directions` | $0.01 |\\n| CoinGecko (price) | `/coingecko/v1/price` | $0.005 |\\n| CoinGecko (markets) | `/coingecko/v1/markets` | $0.005 |\\n| CoinGecko (trending) | `/coingecko/v1/trending` | $0.005 |\\n| Alpha Vantage (quote) | `/alphavantage/v1/quote` | $0.005 |\\n| Alpha Vantage (daily) | `/alphavantage/v1/daily` | $0.005 |\\n| Alpha Vantage (search) | `/alphavantage/v1/search` | $0.005 |\\n\\n### Web & Documents\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Firecrawl Scrape | `/firecrawl/v1/scrape` | $0.01 |\\n| Firecrawl Crawl | `/firecrawl/v1/crawl` | $0.02 |\\n| Firecrawl Map | `/firecrawl/v1/map` | $0.01 |\\n| Firecrawl Extract | `/firecrawl/v1/extract` | $0.02 |\\n| Jina Reader | `/jina/v1/read` | $0.005 |\\n| ScreenshotOne | `/screenshot/v1/capture` | $0.01 |\\n| PDFShift (HTML to PDF) | `/pdfshift/v1/convert` | $0.01 |\\n| QR Code | `/qrcode/v1/generate` | $0.005 |\\n\\n### Translation\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| DeepL (translate) | `/deepl/v1/translate` | $0.005 |\\n| Google Translate | `/translate/v1/translate` | $0.005 |\\n| Google Detect Language | `/translate/v1/detect` | $0.005 |\\n\\n### Intelligence\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Hunter.io (domain search) | `/hunter/v1/search` | $0.02 |\\n| Hunter.io (verify email) | `/hunter/v1/verify` | $0.02 |\\n| IPinfo (IP lookup) | `/ipinfo/v1/lookup` | $0.005 |\\n\\n### Tools & Compute\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Judge0 Code Exec | `/judge0/v1/submissions` | $0.005 |\\n| Judge0 Languages | `/judge0/v1/languages` | $0.005 |\\n| Resend Email | `/resend/v1/emails` | $0.005 |\\n| Resend Batch Email | `/resend/v1/emails/batch` | $0.01 |\\n\\n### Commerce\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Lob Postcards | `/lob/v1/postcards` | $1.00 |\\n| Lob Letters | `/lob/v1/letters` | $1.50 |\\n| Lob Address Verify | `/lob/v1/verify` | $0.01 |\\n| Printful (browse) | `/printful/v1/products` | $0.005 |\\n| Printful (estimate) | `/printful/v1/estimate` | $0.005 |\\n| Printful (order) | `/printful/v1/order` | dynamic |\\n\\n### Messaging\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Pushover | `/pushover/v1/push` | $0.005 |\\n\\n### Security\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| VirusTotal (URL/file scan) | `/virustotal/v1/scan` | $0.01 |\\n\\n### Finance\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| ExchangeRate (rates) | `/exchangerate/v1/rates` | $0.005 |\\n| ExchangeRate (convert) | `/exchangerate/v1/convert` | $0.005 |\\n\\n### Utility\\n| Service | Endpoint | Price |\\n|---------|----------|-------|\\n| Short.io (URL shortener) | `/shortio/v1/shorten` | $0.005 |\\n\\n## Example Commands\\n\\n### Ask an AI model\\n```bash\\nt2000 pay https://mpp.t2000.ai/openai/v1/chat/completions \\\\\\n --data \'{\\"model\\":\\"gpt-4o\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"Explain quantum computing in 3 sentences\\"}]}\'\\n```\\n\\n### Search the web\\n```bash\\nt2000 pay https://mpp.t2000.ai/brave/v1/web/search \\\\\\n --data \'{\\"q\\":\\"latest Sui blockchain news\\"}\'\\n```\\n\\n### Generate an image\\n```bash\\nt2000 pay https://mpp.t2000.ai/fal/fal-ai/flux/dev \\\\\\n --data \'{\\"prompt\\":\\"a futuristic city at sunset, cyberpunk style\\"}\'\\n```\\n\\n### Check weather\\n```bash\\nt2000 pay https://mpp.t2000.ai/openweather/v1/weather \\\\\\n --data \'{\\"q\\":\\"Tokyo\\"}\'\\n```\\n\\n### Send an email\\n```bash\\nt2000 pay https://mpp.t2000.ai/resend/v1/emails \\\\\\n --data \'{\\"from\\":\\"agent@t2000.ai\\",\\"to\\":\\"user@example.com\\",\\"subject\\":\\"Hello\\",\\"text\\":\\"Sent by an AI agent\\"}\'\\n```\\n\\n### Execute code\\n```bash\\nt2000 pay https://mpp.t2000.ai/judge0/v1/submissions \\\\\\n --data \'{\\"source_code\\":\\"print(42)\\",\\"language_id\\":71}\'\\n```\\n\\n### Send physical mail\\n```bash\\n# Send a postcard\\nt2000 pay https://mpp.t2000.ai/lob/v1/postcards \\\\\\n --max-price 2 \\\\\\n --data \'{\\n \\"to\\":{\\"name\\":\\"Jane Doe\\",\\"address_line1\\":\\"123 Main St\\",\\"address_city\\":\\"San Francisco\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94105\\"},\\n \\"from\\":{\\"name\\":\\"AI Agent\\",\\"address_line1\\":\\"456 Oak Ave\\",\\"address_city\\":\\"Palo Alto\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94301\\"},\\n \\"front\\":\\"https://example.com/front.png\\",\\n \\"back\\":\\"https://example.com/back.png\\",\\n \\"use_type\\":\\"operational\\"\\n }\'\\n\\n# Send a letter\\nt2000 pay https://mpp.t2000.ai/lob/v1/letters \\\\\\n --max-price 2 \\\\\\n --data \'{\\n \\"to\\":{\\"name\\":\\"Jane Doe\\",\\"address_line1\\":\\"123 Main St\\",\\"address_city\\":\\"San Francisco\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94105\\"},\\n \\"from\\":{\\"name\\":\\"AI Agent\\",\\"address_line1\\":\\"456 Oak Ave\\",\\"address_city\\":\\"Palo Alto\\",\\"address_state\\":\\"CA\\",\\"address_zip\\":\\"94301\\"},\\n \\"file\\":\\"https://example.com/letter.pdf\\",\\n \\"use_type\\":\\"operational\\",\\n \\"color\\":false\\n }\'\\n\\n# Verify a US address\\nt2000 pay https://mpp.t2000.ai/lob/v1/verify \\\\\\n --data \'{\\"primary_line\\":\\"123 Main St\\",\\"city\\":\\"San Francisco\\",\\"state\\":\\"CA\\",\\"zip_code\\":\\"94105\\"}\'\\n```\\n\\n### Get directions\\n```bash\\nt2000 pay https://mpp.t2000.ai/googlemaps/v1/directions \\\\\\n --data \'{\\"origin\\":\\"San Francisco, CA\\",\\"destination\\":\\"Palo Alto, CA\\"}\'\\n```\\n\\n### Get crypto prices\\n```bash\\nt2000 pay https://mpp.t2000.ai/coingecko/v1/price \\\\\\n --data \'{\\"ids\\":\\"sui,bitcoin,ethereum\\",\\"vs_currencies\\":\\"usd\\"}\'\\n```\\n\\n### Get a stock quote\\n```bash\\nt2000 pay https://mpp.t2000.ai/alphavantage/v1/quote \\\\\\n --data \'{\\"symbol\\":\\"AAPL\\"}\'\\n```\\n\\n### Get breaking news\\n```bash\\nt2000 pay https://mpp.t2000.ai/newsapi/v1/headlines \\\\\\n --data \'{\\"country\\":\\"us\\",\\"category\\":\\"technology\\"}\'\\n```\\n\\n### Translate text\\n```bash\\nt2000 pay https://mpp.t2000.ai/deepl/v1/translate \\\\\\n --data \'{\\"text\\":[\\"Hello, how are you?\\"],\\"target_lang\\":\\"ES\\"}\'\\n```\\n\\n### Semantic search\\n```bash\\nt2000 pay https://mpp.t2000.ai/exa/v1/search \\\\\\n --data \'{\\"query\\":\\"best practices for AI agent payments\\",\\"numResults\\":5}\'\\n```\\n\\n### Read a URL as markdown\\n```bash\\nt2000 pay https://mpp.t2000.ai/jina/v1/read \\\\\\n --data \'{\\"url\\":\\"https://docs.sui.io/concepts/tokenomics\\"}\'\\n```\\n\\n### Google search (structured)\\n```bash\\nt2000 pay https://mpp.t2000.ai/serper/v1/search \\\\\\n --data \'{\\"q\\":\\"Sui blockchain TVL 2026\\"}\'\\n```\\n\\n### Screenshot a webpage\\n```bash\\nt2000 pay https://mpp.t2000.ai/screenshot/v1/capture \\\\\\n --data \'{\\"url\\":\\"https://example.com\\",\\"format\\":\\"png\\",\\"viewport_width\\":\\"1280\\"}\'\\n```\\n\\n### Generate a QR code\\n```bash\\nt2000 pay https://mpp.t2000.ai/qrcode/v1/generate \\\\\\n --data \'{\\"data\\":\\"https://t2000.ai\\",\\"size\\":\\"400x400\\"}\'\\n```\\n\\n### Convert HTML to PDF\\n```bash\\nt2000 pay https://mpp.t2000.ai/pdfshift/v1/convert \\\\\\n --data \'{\\"source\\":\\"https://t2000.ai/docs\\"}\'\\n```\\n\\n### Run a Replicate model\\n```bash\\nt2000 pay https://mpp.t2000.ai/replicate/v1/predictions \\\\\\n --data \'{\\"model\\":\\"meta/llama-3-70b-instruct\\",\\"input\\":{\\"prompt\\":\\"Explain DeFi in 3 sentences\\"}}\'\\n```\\n\\n### Find emails for a domain\\n```bash\\nt2000 pay https://mpp.t2000.ai/hunter/v1/search \\\\\\n --data \'{\\"domain\\":\\"mystenlabs.com\\"}\'\\n```\\n\\n### Look up an IP address\\n```bash\\nt2000 pay https://mpp.t2000.ai/ipinfo/v1/lookup \\\\\\n --data \'{\\"ip\\":\\"8.8.8.8\\"}\'\\n```\\n\\n### Order print-on-demand merchandise\\n```bash\\nt2000 pay https://mpp.t2000.ai/printful/v1/order \\\\\\n --max-price 30 \\\\\\n --data \'{\\"recipient\\":{\\"name\\":\\"Jane Doe\\",\\"address1\\":\\"123 Main St\\",\\"city\\":\\"SF\\",\\"state_code\\":\\"CA\\",\\"country_code\\":\\"US\\",\\"zip\\":\\"94105\\"},\\"items\\":[{\\"variant_id\\":4012,\\"quantity\\":1,\\"files\\":[{\\"url\\":\\"https://example.com/design.png\\"}]}]}\'\\n```\\n\\n### Search for flights\\n```bash\\nt2000 pay https://mpp.t2000.ai/serpapi/v1/flights \\\\\\n --data \'{\\"departure_id\\":\\"LAX\\",\\"arrival_id\\":\\"NRT\\",\\"outbound_date\\":\\"2026-05-01\\",\\"type\\":\\"2\\"}\'\\n```\\n\\n### Convert currency\\n```bash\\nt2000 pay https://mpp.t2000.ai/exchangerate/v1/convert \\\\\\n --data \'{\\"from\\":\\"USD\\",\\"to\\":\\"EUR\\",\\"amount\\":100}\'\\n```\\n\\n### Scan a URL for malware\\n```bash\\nt2000 pay https://mpp.t2000.ai/virustotal/v1/scan \\\\\\n --data \'{\\"url\\":\\"https://suspicious-site.com\\"}\'\\n```\\n\\n### Shorten a URL\\n```bash\\nt2000 pay https://mpp.t2000.ai/shortio/v1/shorten \\\\\\n --data \'{\\"url\\":\\"https://example.com/very/long/url/path\\"}\'\\n```\\n\\n### Send a push notification\\n```bash\\nt2000 pay https://mpp.t2000.ai/pushover/v1/push \\\\\\n --data \'{\\"user\\":\\"USER_KEY\\",\\"message\\":\\"Your agent has a message!\\"}\'\\n```\\n\\n## Flow (automatic)\\n1. Makes initial HTTP request to the URL\\n2. If 402: reads MPP challenge for amount and terms\\n3. If price <= --max-price: pays via Sui USDC\\n4. Retries with credential header\\n5. Returns the API response body\\n\\n## Safety\\n- If requested price exceeds --max-price, payment is refused (no funds spent)\\n- Default max-price: $1.00 USDC per request\\n- For commerce (mail, merch), set --max-price higher\\n- Payment only broadcast after 402 terms are validated\\n\\n## Errors\\n- `PRICE_EXCEEDS_LIMIT`: API asking more than --max-price\\n- `INSUFFICIENT_BALANCE`: not enough available USDC\\n- `UNSUPPORTED_NETWORK`: MPP requires a network other than Sui\\n- `PAYMENT_EXPIRED`: payment challenge has expired\\n- `DUPLICATE_PAYMENT`: nonce already used on-chain\\n\\n## MCP\\nVia MCP: use `t2000_services` to discover services, then `t2000_pay` to call them."},{"name":"t2000-rebalance","description":"Rebalance the wallet to a target allocation by executing multiple swaps in one atomic Payment Intent. Use when asked to rebalance, adjust allocation, \\"shuffle my positions\\", or move from one set of holdings to another. Every leg prices against the same on-chain snapshot \u2014 no cross-leg slippage drift; user signs once.","body":"# t2000: Rebalance Portfolio\\n\\n## Purpose\\nMove from a current allocation to a target allocation by emitting all\\nthe required `swap_execute` calls **in the same assistant turn** so the\\nengine compiles them into one Payment Intent. Result: every leg of the\\nrebalance prices against the same Sui state, slippage is bounded once,\\nand the user signs once.\\n\\n## When to use\\n\\n- \\"Rebalance my portfolio to 60% USDC / 30% SUI / 10% GOLD\\"\\n- \\"Move everything to USDC\\"\\n- \\"Adjust my allocation \u2014 I want less SUI exposure\\"\\n- \\"I\'m 80% SUI, get me to 50/50 with USDC\\"\\n\\n## Flow\\n\\n### Step 1 \u2014 Current allocation\\nCall `balance_check` (engine) or `t2000_balance --json` (CLI) to get the\\ncurrent breakdown. Compute the percentage held in each asset by USD value.\\n\\n### Step 2 \u2014 Plan trades\\nFor each asset, compute the delta vs the target:\\n- Asset over-allocated \u2192 swap **out** to USDC (or another reduce-target asset)\\n- Asset under-allocated \u2192 swap **in** from USDC (or another excess-source asset)\\n\\nPresent the plan to the user **before** executing:\\n\\n```\\n\u{1F4CA} REBALANCE PLAN\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Current Target \u0394\\n USDC $400 $600 +$200\\n SUI $400 $300 \u2212$100\\n GOLD $200 $100 \u2212$100\\n\\nTrades (1 atomic Payment Intent):\\n 1. swap 0.5 SUI \u2192 ~$100 USDC\\n 2. swap 0.05 GOLD \u2192 ~$100 USDC\\n\\nEstimated slippage: 0.3% on each leg\\nProceed?\\n```\\n\\n### Step 3 \u2014 Execute (bundled)\\n\\n**Critical:** emit ALL the `swap_execute` calls as parallel `tool_use` blocks\\n**in the same assistant turn**. The engine\'s permission gate compiles them\\ninto ONE Payment Intent. The user signs once; every leg either succeeds or\\nthe whole rebalance reverts.\\n\\n**Do NOT** call them sequentially across turns \u2014 that defeats the atomicity\\nand exposes the user to price drift between legs.\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: swap_execute({ from: \\"SUI\\", to: \\"USDC\\", amount: 0.5 })\\n tool_use: swap_execute({ from: \\"GOLD\\", to: \\"USDC\\", amount: 0.05 })\\n```\\n\\n### Step 4 \u2014 Summary\\nAfter the Payment Intent settles, call `balance_check` again and show the\\nfinal allocation vs target. Highlight any drift > 1% (caused by slippage\\nor rounding) and ask if the user wants a follow-up swap to close it.\\n\\n## Error handling\\n\\n| Error | Cause | What to do |\\n|---|---|---|\\n| Intent failed \u2014 `INSUFFICIENT_BALANCE` | One of the swap legs would consume more than the wallet holds | Abort the entire intent (no swaps execute). Reduce the amount on the offending leg. |\\n| Intent failed \u2014 `SLIPPAGE_EXCEEDED` | A leg exceeded the configured slippage tolerance | Abort. Re-run with looser slippage OR smaller leg sizes. |\\n| Intent failed \u2014 any reason | Atomic Payment Intent reverts the WHOLE bundle | No funds moved. Tell the user the on-chain state is unchanged. |\\n\\n## CLI fallback (no bundling)\\n\\nThe CLI does not support Payment Intent bundling today. To rebalance from\\nthe CLI, execute swaps one at a time:\\n\\n```bash\\nt2000 swap 0.5 SUI to USDC\\nt2000 swap 0.05 GOLD to USDC\\n```\\n\\nEach swap prices against the on-chain state **at the moment of execution**,\\nwhich means small drift between legs. For larger rebalances ($1k+) prefer\\nthe agent path (which bundles into one Payment Intent).\\n\\n## Fees\\n\\nPer swap leg:\\n- Cetus protocol fee: ~0.1% of swap amount (varies by pool)\\n- Audric overlay fee: 10 bps (~0.1%)\\n\\nBundled rebalances pay the same per-leg fees \u2014 bundling reduces slippage\\nrisk, not fee cost.\\n\\n## Notes\\n\\n- This skill is **engine-first** \u2014 the bundling guarantee only exists in\\n the audric/web chat agent (or any engine consumer with Payment Intent\\n compile support).\\n- For \\"optimize my yield\\" intent (sweep idle USDC into best-APY savings,\\n claim rewards, compare USDC pools), use the `optimize-all` MCP prompt\\n instead \u2014 that\'s a different shape of workflow.\\n- Health-factor check **does not run** for swap-only rebalances (no\\n collateral position changes). For rebalances that involve withdrawing\\n from savings, see `t2000-withdraw` (the safety check runs there)."},{"name":"t2000-receive","description":"Generate a payment request to receive funds into the t2000 agent wallet. Use when asked to receive money, create a payment link, share a wallet address, or generate a QR code for receiving payment. Produces a payment request with address, Sui Payment Kit URI (sui:pay?\u2026), nonce, and optional amount/memo.","body":"# t2000: Receive Payment\\n\\n## Purpose\\nGenerate a payment request containing the agent\'s wallet address, a unique\\nnonce, and a Sui Payment Kit URI (`sui:pay?\u2026`). The sender can scan the QR or\\ncopy the address to send funds. No on-chain transaction is created \u2014 this is a\\nlocal, read-only operation.\\n\\n## Command\\n```bash\\nt2000 receive [options]\\n\\n# Examples:\\nt2000 receive # Address only\\nt2000 receive --amount 25 # Request $25 USDC\\nt2000 receive --amount 100 --memo \\"Invoice #42\\" # With memo\\nt2000 receive --amount 50 --label \\"Freelance work\\" # With label\\nt2000 receive --currency SUI --amount 10 # Request SUI\\n```\\n\\n## Options\\n| Option | Description |\\n|--------|-------------|\\n| `--amount <n>` | Amount to request (omit for open amount) |\\n| `--currency <sym>` | Currency symbol (default: USDC) |\\n| `--memo <text>` | Payment note shown to sender |\\n| `--label <text>` | Description for the payment request |\\n\\n## Output\\n```\\n\u2713 Payment Request\\n\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Address 0x8b3e...d412\\n Network Sui Mainnet\\n Nonce a1b2c3d4-e5f6-7890-abcd-ef1234567890\\n Amount $25.00 USDC\\n Memo Invoice #42\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n\\n Payment URI sui:pay?receiver=0x8b3e...&amount=25000000&...\\n\\n Share this URI or scan the QR to pay via any Sui wallet.\\n```\\n\\n## SDK Usage\\n```typescript\\nconst request = agent.receive({ amount: 25, memo: \'Invoice #42\' });\\n// Returns: { address, network, amount, currency, memo, label, nonce, qrUri, displayText }\\n```\\n\\n## MCP Tool\\nTool name: `t2000_receive` (read-only, auto-approved).\\n\\n## Notes\\n- This is a **local operation** \u2014 no transaction is created, no gas is used\\n- Uses **Sui Payment Kit** \u2014 generates `sui:pay?` URIs with nonce binding\\n- The nonce is a UUID that uniquely identifies each payment request\\n- Wallets that support Payment Kit register payment in an on-chain registry, preventing double-spend\\n- Without `--amount`, the request is open-ended (any amount accepted)\\n- Default currency is USDC; specify `--currency SUI` for native SUI"},{"name":"t2000-repay","description":"Repay outstanding USDC or USDsui debt. Use when asked to repay a loan, pay back debt, reduce outstanding balance, or clear borrows. Supports partial and full repayment. Must repay with the same asset as the original borrow (USDsui debt \u2192 USDsui repay).","body":"# t2000: Repay Borrow\\n\\n## Purpose\\nRepay outstanding debt in USDC or USDsui. Supports specific amounts or `repay all` to clear the full balance including accrued interest. **Symmetry rule (v0.51.1+):** repay with the same asset as the original borrow.\\n\\n## Rules\\n\\n1. **Repay with the same asset as the borrow.** A USDsui debt MUST be repaid with USDsui. A USDC debt MUST be repaid with USDC. The SDK fetches the matching coin type per borrow asset.\\n2. **Don\'t auto-swap to bridge the asset gap.** If the user holds only the wrong stable, tell them to swap manually first via `t2000-swap` \u2014 never auto-chain swap + repay.\\n3. **`repay all` clears across both stables.** When `--asset` is omitted, `repay all` resolves to \\"clear every outstanding debt\\" \u2014 the SDK iterates per asset.\\n4. **Surface remaining debt + new HF.** After repayment, state the new debt + health factor. Users who just repaid usually want to plan the next move (withdraw, re-borrow at better terms).\\n5. **No protocol fee on repay.** NAVI doesn\'t charge on repayment \u2014 the interest spread is captured at the lending rate, not at repay-time.\\n\\n## Command\\n```bash\\nt2000 repay <amount> [--asset USDC|USDsui]\\nt2000 repay all [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 repay 20 # 20 USDC (default \u2014 clears USDC debt)\\nt2000 repay 20 --asset USDsui # 20 USDsui (clears USDsui debt)\\nt2000 repay all # clear ALL debts across both stables\\nt2000 repay all --asset USDsui # clear ONLY USDsui debt\\n```\\n\\nWhen `--asset` is omitted and the wallet has only one debt type, the SDK auto-selects. When both debts exist, omitting `--asset` resolves to \\"highest-APY debt first\\" (CLI) or \\"repay all stables\\" for `repay all`.\\n\\n## Fees\\n- No protocol fee on repayment\\n\\n## Output\\n```\\n\u2713 Repaid $XX.XX <asset>\\n Remaining Debt: $XX.XX\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Notes\\n- `repay all` calculates full outstanding principal + accrued interest for the targeted asset (or every asset if `--asset` omitted).\\n- Available balance of the matching stable must cover the repayment amount. If short, surface the shortfall and the swap path \u2014 do not auto-execute.\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent:\\n1. Call `health_check` to see active debts per asset.\\n2. For each debt the user wants to clear, emit `repay_debt({ amount, asset })`.\\n3. If clearing multiple debts in one go, emit them as parallel `tool_use` blocks in the same assistant turn \u2014 the engine compiles into one Payment Intent (atomic).\\n4. After settlement, surface new debt + new HF."},{"name":"t2000-safeguards","description":"Configure spending limits and safety controls for t2000 agent wallets. Use when asked to set transaction limits, daily send limits, lock or unlock the agent, view safeguard settings, or protect the wallet from unauthorized spending. Required before enabling MCP server access.","body":"# t2000: Agent Safeguards\\n\\n## Purpose\\nConfigure spending limits and safety guardrails for autonomous agent\\noperation. Three controls: agent lock (kill switch), per-transaction\\nlimit, and daily send limit.\\n\\n> Safeguards are enforced on CLI and MCP. All state-changing actions\\n> require explicit confirmation before execution.\\n\\n## Commands\\n```bash\\nt2000 config show # view all safeguard settings\\nt2000 config set maxPerTx 500 # max $500 per outbound transaction\\nt2000 config set maxDailySend 1000 # max $1000 outbound per day\\nt2000 lock # freeze ALL operations immediately\\nt2000 unlock # resume operations (requires PIN)\\n```\\n\\n## Controls\\n\\n| Control | Description | Default |\\n|---------|-------------|---------|\\n| `maxPerTx` | Max USDC per single outbound op (send/pay) | 0 (unlimited) |\\n| `maxDailySend` | Max total USDC outbound per calendar day | 0 (unlimited) |\\n| `locked` | Kill switch \u2014 freezes ALL operations | false |\\n\\n## What counts as outbound\\n- `t2000 send` \u2014 transfers to other addresses\\n- `t2000 pay` \u2014 MPP API payments\\n\\n## What is NOT limited\\nInternal operations (save, withdraw, borrow, repay)\\nmove funds within the agent\'s own wallet and protocol positions. They\\nare not subject to send limits.\\n\\n## Output (config show)\\n```\\n Agent Safeguards\\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n Locked: No\\n Per-transaction: $500.00\\n Daily send limit: $1,000.00 ($350.00 used today)\\n```\\n\\n## Blocked output\\n```\\n \u2717 Blocked: amount $1,000.00 exceeds per-transaction limit ($500.00)\\n \u2717 Blocked: daily send limit reached ($1,000.00/$1,000.00 used today)\\n \u2717 Agent is locked. All operations frozen.\\n```\\n\\n## JSON mode\\n```bash\\nt2000 config show --json\\n```\\n```json\\n{ \\"locked\\": false, \\"maxPerTx\\": 500, \\"maxDailySend\\": 1000, \\"dailyUsed\\": 350 }\\n```\\n\\n## SDK\\n```typescript\\nconst agent = await T2000.create({ pin });\\n\\n// Check config\\nagent.enforcer.getConfig(); // { locked, maxPerTx, maxDailySend, dailyUsed, ... }\\nagent.enforcer.isConfigured(); // true if any limit is non-zero\\n\\n// Set limits\\nagent.enforcer.set(\'maxPerTx\', 500);\\nagent.enforcer.set(\'maxDailySend\', 1000);\\n\\n// Lock/unlock\\nagent.enforcer.lock();\\nagent.enforcer.unlock();\\n```\\n\\n## Important\\n- Safeguards are opt-in \u2014 defaults are permissive (0 = unlimited)\\n- MCP server requires non-zero limits before starting\\n- Lock freezes ALL operations (including internal) as a safety measure\\n- Daily counter resets at midnight UTC"},{"name":"t2000-save","description":"Deposit USDC or USDsui into savings to earn yield on Sui via NAVI Protocol. Use when asked to save money, earn interest, deposit to savings, \\"swap and save\\" a non-USDC token, or put funds to work. Not for sending to other addresses \u2014 use t2000-send for that.","body":"# t2000: Save (Deposit to Savings)\\n\\n## Purpose\\nDeposit **USDC or USDsui** into savings to earn yield on NAVI Protocol. Funds remain non-custodial and\\nwithdrawable at any time. USDsui is permitted as a strategic exception (v0.51.0+) because it has\\nits own NAVI pool, often at a different APY than USDC. Every other token (GOLD, SUI, USDT, USDe,\\nETH, NAVX, WAL) is **not saveable** \u2014 swap to USDC or USDsui first.\\n\\n## Rules\\n\\n1. **Only USDC or USDsui save.** The SDK enforces it via `assertAllowedAsset(\'save\', asset)`; other tokens return `UNSUPPORTED_ASSET`.\\n2. **Don\'t auto-swap.** If the user says \\"save 10 SUI\\", confirm the swap-and-save intent first \u2014 some users want to keep SUI exposure.\\n3. **Engine bundling: same turn or not at all.** When you need swap + save, emit BOTH `tool_use` blocks in the same assistant turn so the engine compiles ONE atomic Payment Intent. Never call them in separate turns \u2014 that loses atomicity and exposes price drift.\\n4. **Preview is mandatory.** Before emitting, always surface: source token + amount, estimated USDC received (from `swap_quote`), save APY, total fees. The user signs once but the LLM walks them through the math first.\\n5. **CLI users get sequential.** The CLI doesn\'t bundle. Run `t2000 swap` then `t2000 save all` \u2014 accept small drift for amounts under $1k.\\n\\n## Command\\n```bash\\nt2000 save <amount> [--asset USDC|USDsui]\\nt2000 save all [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 save 80 # 80 USDC (default)\\nt2000 save 80 --asset USDsui # 80 USDsui\\nt2000 save all # full USDC balance (minus $1 gas reserve)\\nt2000 save all --asset USDsui # full USDsui balance (minus 1.0 reserve)\\n```\\n\\n- `save all`: deposits full available balance of the chosen asset minus 1.0 of that asset for safety\\n- `--asset` defaults to USDC when omitted\\n\\n## Fees\\n- Protocol fee: 0.1% on deposit (collected atomically on-chain)\\n\\n## Output\\n```\\n\u2713 Gas manager: $1.00 USDC \u2192 SUI [only shown if auto-topup triggered]\\n\u2713 Saved $XX.XX <asset> to best rate\\n\u2713 Current APY: X.XX%\\n\u2713 Savings balance: $XX.XX <asset>\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Notes\\n- APY is variable based on protocol utilization (USDC and USDsui pools quote independently)\\n- If available balance of the chosen asset is too low, returns INSUFFICIENT_BALANCE\\n- `t2000 supply` is an alias for `t2000 save`\\n- **Repay symmetry (v0.51.1+):** if you borrow USDsui, you must repay with USDsui (and USDC borrows must repay with USDC) \u2014 the SDK fetches the matching coin type per borrow asset.\\n\\n## Saving a non-USDC token (\\"swap and save\\")\\n\\nIf the user wants to save a token that\'s **not** USDC or USDsui \u2014 GOLD,\\nSUI, USDT, USDe, ETH, NAVX, WAL \u2014 the agent must swap first, then save.\\nThe right flow depends on the consumer:\\n\\n### Engine (audric/web) \u2014 bundled atomic swap + save\\n\\nEmit BOTH tool_use blocks in the SAME assistant turn. The engine\'s\\npermission gate compiles them into ONE Payment Intent: the swap\'s\\n`received` coin handles off as the save\'s input via coin-ref inside the\\nsame PTB. Atomic \u2014 both succeed or both revert. User signs once.\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: swap_execute({ from: \\"SUI\\", to: \\"USDC\\", amount: 1.0 })\\n tool_use: save_deposit({ amount: <swap_received>, asset: \\"USDC\\" })\\n```\\n\\nBefore emitting, **always preview** to the user:\\n- The source token + amount being swapped\\n- Estimated USDC received (from `swap_quote`)\\n- The save APY they\'ll earn\\n- Total fees (Cetus + Audric overlay + NAVI save fee)\\n\\n**Do NOT** call swap then save in separate turns \u2014 that loses atomicity\\nand exposes the user to price drift between the legs.\\n\\n**Do NOT** auto-decide for the user. If they say \\"save 10 SUI\\", confirm\\nthe intent: \\"That requires swapping ~10 SUI to ~$XX USDC first, then\\ndepositing. Proceed?\\" Some users want to hold SUI.\\n\\n### CLI \u2014 sequential (no bundling)\\n\\nThe CLI doesn\'t support Payment Intent bundling. Run two commands:\\n\\n```bash\\nt2000 swap 1.0 SUI to USDC\\nt2000 save all\\n```\\n\\nEach command prices against on-chain state at the moment of execution,\\nso there\'s small price drift between them. For large amounts ($1k+),\\nprefer the agent path which bundles into one Payment Intent.\\n\\n### What\'s NOT saveable\\n\\nGOLD, SUI, USDT, USDe, ETH, NAVX, WAL \u2014 none of these have NAVI lending\\npools today, so they can\'t be saved directly. Must swap to USDC or\\nUSDsui first. This is enforced by the SDK\'s `assertAllowedAsset(\'save\',\\nasset)` allow-list \u2014 calling `save_deposit({ asset: \'SUI\' })` returns\\n`UNSUPPORTED_ASSET`."},{"name":"t2000-send","description":"Send USDC from the t2000 agent wallet to another address on Sui. Use when asked to pay someone, transfer funds, send money, tip a creator, or make a payment to a specific Sui address or saved contact. Do NOT use for API payments \u2014 use t2000-pay for MPP-protected services.","body":"# t2000: Send USDC\\n\\n## Purpose\\nTransfer USDC from the agent\'s available balance to any Sui address. Gas is\\nself-funded from the agent\'s SUI reserve (auto-topped up if needed).\\n\\n## Rules\\n\\n1. **Validate the recipient first.** Names \u2192 contacts lookup; `0x...` \u2192 `isValidSuiAddress()`. Refuse with `INVALID_ADDRESS` on a malformed address; don\'t guess.\\n2. **Resolve SuiNS over contacts when both exist.** `alex.sui` is preferred over a local contact named `alex` \u2014 SuiNS is the global standard. The contacts subsystem is deprecated and will sunset.\\n3. **Sends are single-write.** Never bundle with another write in a Payment Intent. Each transfer is its own intent. If you need send + something else, sequence them across turns.\\n4. **Don\'t auto-save raw addresses.** After a send to an unknown address, OFFER to save as contact but require the user to provide a name. Cluttered contacts hurt UX.\\n5. **Amount precision matters.** Floor to USDC\'s 6 decimals (or 2 for display). Never round up \u2014 `Math.round` can produce a number larger than the on-chain balance and the transfer will fail simulation.\\n6. **Multi-recipient = multiple sends.** A \\"send to A, B, C\\" request emits N parallel `send_transfer` tool calls; the engine compiles them into atomic bundles of up to 4 per Payment Intent (host splits across multiple intents if N > 4).\\n\\n## Command\\n```bash\\nt2000 send <amount> <asset> to <address_or_contact>\\nt2000 send <amount> <asset> <address_or_contact>\\n\\n# Examples:\\nt2000 send 10 USDC to 0x8b3e...d412\\nt2000 send 50 USDC to Tom\\nt2000 send 50 USDC 0xabcd...1234\\n```\\n\\nThe `to` keyword is optional. The recipient can be a Sui address (0x...) or a\\nsaved contact name (e.g. \\"Tom\\"). Use `t2000 contacts` to list saved contacts.\\n\\n## Pre-flight checks (automatic)\\n1. Sufficient available USDC balance\\n2. SUI gas reserve present; if not, auto-topup triggers transparently\\n\\n## Output\\n```\\n\u2713 Sent $XX.XX USDC \u2192 0x8b3e...d412\\n Gas: X.XXXX SUI (self-funded)\\n Balance: $XX.XX USDC\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Error handling\\n- `INSUFFICIENT_BALANCE`: available balance is less than the requested amount\\n- `INVALID_ADDRESS`: destination is not a valid Sui address\\n- `CONTACT_NOT_FOUND`: name is not a saved contact or valid address\\n- `SIMULATION_FAILED`: transaction would fail on-chain; details in error message\\n\\n## Recipient resolution flow\\n\\nWhen the user provides a recipient, resolve it before broadcasting:\\n\\n1. **Name given** \u2192 look up in saved contacts. If found, use the mapped\\n address. If not found and not a valid `0x...` address, ask the user\\n to clarify (suggest `t2000 contacts add <name> <address>` first).\\n2. **Address given (`0x...`)** \u2192 validate with `isValidSuiAddress()`. If\\n invalid, refuse with `INVALID_ADDRESS`.\\n3. **Ambiguous** (looks like a name AND a valid prefix) \u2192 ask the user\\n which they meant.\\n\\nAfter a successful send to a **previously-unknown raw address** (not a\\nsaved contact), offer to save it:\\n\\n> \\"Want to save 0x8b3e\u2026d412 as a contact? Say `yes <name>` to save.\\"\\n\\nIf the user provides a name, call `t2000 contacts add <name> <address>`\\n(CLI). This makes future sends to the same person work by name\\n(`t2000 send 10 USDC to <name>`). The engine no longer ships a\\n`save_contact` tool \u2014 contacts are CLI-only state today; audric users\\nmanage contacts via the send screen.\\n\\n**Do not auto-save** without asking \u2014 the user might not want every\\none-off recipient cluttering their contacts list.\\n\\n## Engine orchestration (audric/web)\\n\\nWhen called inside the Audric chat agent:\\n\\n1. Resolve recipient (contacts lookup or address validation) \u2014 no tool call needed for contacts; resolution happens in prose.\\n2. Call `balance_check` to confirm sufficient funds.\\n3. Emit `send_transfer({ to, amount, asset })` as the write tool_use.\\n4. After the send settles, if the recipient was a raw address not already\\n in contacts, surface the \\"save as contact?\\" prompt to the user (see\\n above). The user confirms in the next turn; the host (CLI / audric)\\n handles persistence \u2014 the engine has no contact-write tool.\\n\\nSends are **single-write** \u2014 never bundle with another write in a\\nPayment Intent. Each transfer is its own intent."},{"name":"t2000-setup","description":"Set up a t2000 Agentic Wallet end-to-end on the user\'s machine. Use when the user says \\"set up t2000\\", \\"install the wallet\\", \\"create my Agentic Wallet\\", \\"connect t2000 to Claude / Cursor\\", or pastes a one-prompt install URL. Covers wallet creation, PIN, safeguards, and MCP wiring. Read this first when bootstrapping a new user; the other skills assume this has run.","body":"# t2000: Agentic Wallet \u2014 One-Prompt Setup\\n\\n## Purpose\\n\\nGet a fresh user from \\"nothing installed\\" to \\"Agentic Wallet ready\\" in under 5 minutes. This is the canonical entry point for the **one-prompt install** UX:\\n\\n```\\nRun curl -sL https://t2000.ai/skills/t2000-setup, and use the returned setup\\ninstructions to set up my Agentic Wallet.\\n```\\n\\nWhen invoked through that prompt, the LLM fetches this file, then executes the steps below in order.\\n\\n## Rules\\n\\n1. **Walk the steps in order.** Each step depends on the previous one. Skipping breaks setup.\\n2. **Surface, don\'t store, the PIN.** Tell the user to write it down. Never echo or persist their PIN in agent memory.\\n3. **Stop at the first failure.** If `t2000 init` errors, do not proceed to step 3; report the error and ask the user to retry.\\n4. **Confirm AI-client choice before MCP install.** Don\'t assume Claude Desktop vs. Cursor vs. Windsurf \u2014 ask which they use, then pick the matching config path.\\n5. **Setup is read + write \u2014 show, then ask.** Echo each command you\'re about to run. The user runs it (or confirms you can). Never silently shell out.\\n\\n## Steps\\n\\n### Step 1 \u2014 Install the CLI\\n\\n```bash\\nnpm install -g @t2000/cli\\n```\\n\\nVerify:\\n```bash\\nt2000 --version\\n# Should print: 3.x.x (beta)\\n```\\n\\nIf `npm` is missing, point the user to https://nodejs.org/ (Node 18+).\\n\\n### Step 2 \u2014 Create a wallet\\n\\n```bash\\nt2000 init\\n```\\n\\nThis is interactive:\\n- Prompts for a PIN \u2014 the user types it; **you do not handle this**.\\n- Generates a fresh Ed25519 keypair on Sui mainnet.\\n- Prints the wallet address.\\n\\nAfter init completes, ask the user to record the PIN somewhere safe (it encrypts the local key file at `~/.t2000/wallet.key`).\\n\\n### Step 3 \u2014 Fund the wallet\\n\\n```bash\\nt2000 fund\\n```\\n\\nShows the deposit address + supported networks. Tell the user:\\n- Send USDC to the printed address on **Sui mainnet** (not Solana, not Ethereum).\\n- Keep ~0.05 SUI on hand for gas (or let `t2000 swap` top it up later).\\n- 1 USDC minimum to get going.\\n\\n### Step 4 \u2014 Configure safeguards (required for MCP)\\n\\n```bash\\nt2000 config set maxPerTx 100\\nt2000 config set maxDailySend 500\\n```\\n\\nThe MCP server **refuses to start** without these. Defaults are conservative ($100 per transaction, $500 per day); the user can raise them later via `t2000 config set`.\\n\\n### Step 5 \u2014 Install MCP into the user\'s AI client\\n\\nAsk the user which AI client they use, then run:\\n\\n```bash\\nt2000 mcp install\\n```\\n\\nThis is interactive \u2014 it discovers installed clients (Claude Desktop, Cursor, Windsurf, Cline, Continue) and offers a multi-select. The CLI writes the correct config block into each chosen client.\\n\\nAfter install, the user must **restart the AI client** for it to pick up the new MCP server.\\n\\n### Step 6 \u2014 Verify\\n\\n**6a \u2014 CLI smoke** (in the same terminal):\\n```bash\\nt2000 balance\\n```\\n\\nShould print:\\n- Wallet address (last 6 chars match step 2)\\n- Available USDC (matches step 3 funding, or $0.00 if not yet funded)\\n- Gas reserve (SUI)\\n- Total\\n\\n**6b \u2014 AI client tool smoke** (after restart):\\n```\\nWhat\'s my t2000 balance?\\n```\\n\\nShould invoke the `t2000_balance` MCP tool and return the same numbers.\\n\\n**6c \u2014 AI client prompt smoke** (this is what most users miss):\\n\\nThe MCP server doesn\'t just expose tools \u2014 it ALSO exposes 35 prompts. Type `/` in the AI client\'s chat input to open the prompt picker. You should see:\\n\\n- 17 core wallet `skill-` entries (`skill-balance`, `skill-save`, `skill-borrow`, etc.) \u2014 canonical t2000 skills as MCP prompts.\\n- 4 MPP recipe `skill-mpp-*` entries (`skill-mpp-image-gen`, `skill-mpp-gpt4o`, `skill-mpp-transcription`, `skill-mpp-index`) \u2014 deep dives for paying paid APIs via `t2000 pay`.\\n- 14 workflow prompts (`financial-report`, `optimize-yield`, `sweep`, `risk-check`, etc.) \u2014 multi-skill orchestrations.\\n\\nRun `/skill-balance` (or just type and accept the autocomplete). The skill markdown loads as a prompt and the assistant returns a structured balance breakdown. Try `/financial-report` for the full-account view. Try `/skill-mpp-image-gen` to see how to generate an image via `t2000 pay`.\\n\\n**Why this matters:** users often paste the one-prompt-install command above, see the t2000 tools work, but don\'t realize they also have 21 skill prompts + 14 workflow prompts available. Surface this so they discover the agentic surface, not just the tool calls.\\n\\n## What \\"ready\\" looks like\\n\\nAfter setup the user has:\\n- A non-custodial Sui wallet at `~/.t2000/wallet.key` (encrypted with their PIN).\\n- Optional USDC + SUI funded on Sui mainnet.\\n- Configured per-tx + daily safeguards.\\n- An MCP server wired into Claude / Cursor / Windsurf etc. \u2014 Audric-style chat that can actually move money under user confirmation.\\n\\n## What setup does NOT do\\n\\n- **Does not move money.** Setup is read + config only. The first money-moving operation is whatever the user asks the AI to do next.\\n- **Does not export or back up the private key.** The key lives in `~/.t2000/wallet.key` and is encrypted by the PIN. To back up, the user runs `t2000 export` manually \u2014 never volunteer this unless asked.\\n- **Does not bypass safeguards.** Even with MCP installed, every write tap-to-confirms through the AI client; safeguards apply server-side.\\n\\n## Next steps to suggest\\n\\nAfter verify succeeds, surface a short menu of natural next moves:\\n- \\"Earn yield on your USDC\\" \u2192 `t2000-save`\\n- \\"Send USDC to someone\\" \u2192 `t2000-send`\\n- \\"Connect more AI clients\\" \u2192 `t2000-mcp`\\n- \\"See what else t2000 can do\\" \u2192 run `t2000 --help` or browse https://t2000.ai/skills\\n\\n## Troubleshooting\\n\\n| Symptom | Fix |\\n|---|---|\\n| `t2000: command not found` after npm install | `npm bin -g` directory not on PATH; add it or use `npx @t2000/cli ...` instead |\\n| `t2000 init` fails with permission error | Don\'t run with `sudo`; npm global may need a user-level prefix (`npm config set prefix ~/.npm-global`) |\\n| MCP server \\"doesn\'t do anything\\" when run manually | Working as designed \u2014 the server is a subprocess launched by the AI client, never run from a terminal. See `t2000-mcp` skill. |\\n| AI client doesn\'t see `t2000_*` tools after install | Restart the client. If still missing, check the per-client config path printed by `t2000 mcp install`. |"},{"name":"t2000-swap","description":"Swap tokens on Sui via Cetus Aggregator (20+ DEXs, best-route across SUI, USDC, USDsui, USDT, USDe, ETH, GOLD, NAVX, WAL, vSUI, and more). Use when asked to swap, trade, convert, exchange, or \\"turn X into Y\\". Also use as a preflight inside the engine\'s \\"swap and save\\" / \\"swap and pay\\" bundled flows. Do not use for sending \u2014 use t2000-send for transfers.","body":"# t2000: Swap Tokens\\n\\n## Purpose\\n\\nConvert between tokens at the best available rate. Cetus Aggregator routes across 20+ DEXs and picks the lowest-price-impact path. Slippage defaults to 1%; configurable up to 5%.\\n\\n## Rules\\n\\n1. **Preview before signing.** Always run `t2000 swap-quote ...` (or call `swap_quote` in the engine) and surface `priceImpact` + `toAmount` to the user before broadcasting.\\n2. **Decline obviously bad swaps.** If `priceImpact > 0.5%` (50 bps), warn the user and require explicit confirmation. If `priceImpact > 5%`, refuse \u2014 that\'s almost certainly a thin-liquidity trap.\\n3. **One swap per intent.** Cetus aggregator handles multi-hop internally; do not chain `swap` calls.\\n4. **Don\'t auto-decide stables.** If the user says \\"swap to USD\\", ASK whether USDC or USDsui \u2014 they have different NAVI pool APYs.\\n5. **Engine path is the swap-and-save / swap-and-pay anchor.** When the user asks \\"save my SUI\\", the engine emits `swap_execute` + `save_deposit` in the SAME turn \u2192 atomic Payment Intent. See the `t2000-save` skill for the bundling contract.\\n\\n## Command\\n\\n```bash\\nt2000 swap <amount> <from> [for] <to> [--slippage <pct>]\\n\\n# Examples:\\nt2000 swap 100 USDC SUI # 100 USDC \u2192 SUI, default 1% slippage\\nt2000 swap 100 USDC for SUI # same; `for` keyword is optional\\nt2000 swap 5 SUI USDC --slippage 2 # 5 SUI \u2192 USDC, 2% slippage\\nt2000 swap 50 USDC USDsui # stable-to-stable; usually <0.05% impact\\n```\\n\\nSlippage is capped at 5% (any higher is rejected \u2014 that\'s degenerate liquidity).\\n\\n## Preview (no signing)\\n\\n```bash\\nt2000 swap-quote <amount> <from> <to>\\n```\\n\\nReturns:\\n- `toAmount` \u2014 estimated output (at current pool state)\\n- `priceImpact` \u2014 basis points moved by the trade\\n- `route` \u2014 provider name(s) Cetus selected\\n\\n## Fees\\n\\n- **Network gas:** ~0.001-0.01 SUI per swap (self-funded from the wallet)\\n- **Cetus protocol fee:** typically 0.05-0.30% depending on the pool tier (already baked into `toAmount`)\\n- **t2000 / CLI:** zero fee. Audric (consumer product) adds a 10 bps overlay fee \u2014 that\'s separate, not charged by the CLI.\\n\\n## Output\\n\\n```\\n\u2713 Swapped 100 USDC for 49.8721 SUI\\n Price Impact: 0.04%\\n Route: USDC \u2192 SUI (Cetus \u2192 Turbos)\\n Gas: 0.0038 SUI\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Engine orchestration\\n\\nWhen called inside the Audric chat agent, `swap_execute` always pairs with a `swap_quote` first turn (or fresh quote inside the same turn) so the LLM can:\\n1. Compute the projected output value in USD via `token_prices`.\\n2. Surface a confirm card with: `fromAmount`, `toAmount`, `priceImpact`, `route`, `fee`.\\n3. Block on user confirm \u2014 every swap is `permissionLevel: \'confirm\'` (no auto-execute under zkLogin).\\n\\nFor \\"swap and save\\" \u2014 emit `swap_execute` + `save_deposit` in the same assistant turn so the engine compiles one atomic Payment Intent. See `t2000-save` for the full bundle contract.\\n\\n## Error handling\\n\\n- `SWAP_NO_ROUTE` \u2014 no path from `from` to `to` in Cetus\'s pool graph. Suggest going via USDC as an intermediate.\\n- `INSUFFICIENT_LIQUIDITY` \u2014 the requested size moves the pool too far. Suggest a smaller trade or splitting.\\n- `INSUFFICIENT_BALANCE` \u2014 wallet doesn\'t hold enough of the source token (after gas reserve).\\n- `SLIPPAGE_EXCEEDED` \u2014 by the time the tx confirmed, the pool moved past the slippage limit. Retry with the same params; usually transient.\\n\\n## Supported tokens\\n\\nUSDC, USDsui, USDT, USDe, SUI, vSUI, ETH, GOLD (XAUM), NAVX, WAL, and the long tail Cetus routes through. Use the canonical symbol or pass a full coin type (`0x...::module::TYPE`). The `t2000` token registry resolves common symbols automatically.\\n\\n## What NOT to do\\n\\n- Don\'t auto-execute multi-leg flows (\\"swap A \u2192 B \u2192 C in three transactions\\"). If a multi-hop is needed, Cetus does it internally as one PTB.\\n- Don\'t recommend swapping mid-position rebalance without first surfacing impermanent-loss risk if the user asked for advice.\\n- Don\'t swap to a stable just to \\"park\\" funds \u2014 point them at `t2000-save` instead (yield > 0)."},{"name":"t2000-withdraw","description":"Withdraw from savings and receive USDC or USDsui. Use when asked to withdraw from savings, access deposited funds, pull money out of savings, reduce yield position, \\"close my position\\", or emergency withdraw. For sending to another address, use t2000-send.","body":"# t2000: Withdraw from Savings\\n\\n## Purpose\\nWithdraw USDC or USDsui from savings back to your checking balance.\\n\\n## Rules\\n\\n1. **Withdraw is NOT a wallet read.** It moves funds OUT of NAVI back into the wallet. To check wallet USDC balance use `t2000-check-balance`.\\n2. **HF check is mandatory when debt exists.** If the withdrawal drops HF below 1.5, refuse with `WITHDRAW_WOULD_LIQUIDATE`. Surface `safeWithdrawAmount` from error data.\\n3. **Default is USDC; explicit `--asset USDsui` for USDsui positions.** Two separate NAVI pool positions \u2014 they don\'t auto-merge.\\n4. **\\"Close my position\\" = bundled repay + withdraw.** When the user has debt and wants out, emit `repay_debt(all)` + `withdraw(remaining)` in the SAME turn so the engine compiles ONE atomic Payment Intent. Never sequence them across turns \u2014 exposes the wallet to a partial-close window.\\n5. **Repay symmetry still applies to the bundle.** `repay_debt` MUST use the SAME asset as the original borrow (USDsui debt \u2192 USDsui repay). If the user doesn\'t hold enough of the matching asset, abort with a clear message \u2014 do not auto-swap.\\n\\n## Command\\n```bash\\nt2000 withdraw <amount> [--asset USDC|USDsui]\\nt2000 withdraw all [--asset USDC|USDsui]\\n\\n# Examples:\\nt2000 withdraw 25 # 25 USDC (default)\\nt2000 withdraw 25 --asset USDsui # 25 USDsui\\nt2000 withdraw all # full USDC savings position\\nt2000 withdraw all --asset USDsui # full USDsui savings position\\n```\\n\\n`--asset` defaults to USDC when omitted.\\n\\n## Fees\\n- No protocol fee on withdrawals\\n\\n## Output\\n```\\n\u2713 Withdrew $XX.XX <asset>\\n Tx: https://suiscan.xyz/mainnet/tx/0x...\\n```\\n\\n## Safety check (active when debt exists)\\n\\nIf the wallet has outstanding debt, t2000 evaluates whether the withdrawal\\nwould push the health factor below 1.5:\\n\\n| Scenario | Behavior |\\n|---|---|\\n| No debt | Withdrawal proceeds \u2014 no HF check. |\\n| Withdrawal keeps HF \u2265 1.5 | Withdrawal proceeds \u2014 note the new HF in the output. |\\n| Withdrawal would drop HF < 1.5 | **Refused** with `WITHDRAW_WOULD_LIQUIDATE`. Error data includes `safeWithdrawAmount` (the largest amount that keeps HF \u2265 1.5). |\\n\\n## Emergency / \\"close my position\\" flow\\n\\nWhen the user asks to \\"withdraw everything\\", \\"close my position\\", or\\n\\"emergency withdraw\\":\\n\\n### Step 1 \u2014 Read state\\nCall `health_check` (engine) or `t2000 balance --show-limits` (CLI) to\\nsee savings, debt, and current HF.\\n\\n### Step 2 \u2014 Decide path\\n\\n| Wallet state | Path |\\n|---|---|\\n| **No debt** | Single-write `withdraw all` for each asset held in savings. |\\n| **Has debt, savings \u2265 debt** | **Bundled repay + withdraw** \u2014 emit `repay_debt(all)` and `withdraw(remaining)` as parallel `tool_use` blocks in the SAME assistant turn. Engine compiles into one Payment Intent: atomic repay-then-withdraw, one signature. |\\n| **Has debt, savings < debt** | **Refuse** \u2014 user can\'t fully close position without first acquiring more of the borrowed asset. Tell them how much more they\'d need; do not auto-swap. |\\n\\n### Step 3 \u2014 Bundled emit (engine path)\\n\\nFor the \\"bundled repay + withdraw\\" case, emit BOTH tool_use blocks in the\\nsame assistant turn:\\n\\n```\\n[ASSISTANT TURN \u2014 emit in parallel]\\n tool_use: repay_debt({ amount: <debt>, asset: <borrowed_asset> })\\n tool_use: withdraw({ amount: <remaining>, asset: <savings_asset> })\\n```\\n\\nThe engine\'s permission gate compiles these into ONE Payment Intent. Both\\nlegs succeed or both revert \u2014 no partial close. The user signs once.\\n\\n**Do NOT** call them sequentially across turns \u2014 that loses atomicity and\\nexposes the user to a window where debt is repaid but the withdraw fails,\\nleaving the wallet in an awkward state.\\n\\n**Critical:** `repay_debt` MUST use the SAME asset as the original borrow\\n(USDsui debt \u2192 USDsui repay, USDC debt \u2192 USDC repay \u2014 see `t2000-repay`).\\nIf the user doesn\'t hold enough of the matching asset, abort with a clear\\nmessage; do not auto-swap.\\n\\n## Error handling\\n- `WITHDRAW_WOULD_LIQUIDATE` \u2014 withdrawal would push HF < 1.5. Use `safeWithdrawAmount` from error data, or repay debt first.\\n- `NO_COLLATERAL` \u2014 no savings position in the requested asset.\\n- `INSUFFICIENT_BALANCE` \u2014 requested amount exceeds savings balance.\\n- Intent failed (bundled flow) \u2014 atomic revert. No funds moved."},{"name":"t2000-yields","description":"Compare yield opportunities across t2000 \u2014 current save / borrow APYs for USDC and USDsui on NAVI, and the user\'s current earning positions. Use when asked \\"what\'s the best yield?\\", \\"where should I park USDC?\\", \\"should I save USDC or USDsui?\\", \\"what\'s my earning rate?\\", or \\"compare yields\\". Pairs with t2000-save (action) and t2000-rebalance (multi-leg planning).","body":"# t2000: Compare Yields\\n\\n## Purpose\\n\\nSurface every earning opportunity the user has on t2000 \u2014 current NAVI pool APYs (USDC + USDsui, save + borrow), the user\'s open positions, and earnings so far. Helps the user choose where to deploy idle funds without dragging them through five different commands.\\n\\n> **Note (S.323 / 2026-05-25):** Liquid staking via VOLO was removed from t2000 entirely. SUI staking is no longer a t2000 yield option. If the user holds SUI and wants yield, swap to USDC (or USDsui) and save \u2014 that is the only yield path t2000 exposes today.\\n\\n## Rules\\n\\n1. **Always read live state.** Cache nothing \u2014 APY swings hourly. Run `t2000 rates` (or `rates_info` in the engine) every time the user asks.\\n2. **Compare apples-to-apples.** USDC and USDsui have separate NAVI pools at different APYs; surface both with the spread. Don\'t lead with \\"the USDC rate\\" when USDsui is paying more.\\n3. **Strip the marketing lift.** NAVI\'s quoted APY includes liquidity-mining rewards in some pools \u2014 net APY (lending only) is the durable number. Surface both if the rates feed splits them.\\n4. **Yield \u2260 free.** When recommending a save, also surface: smart-contract risk (NAVI is battle-tested but non-zero), liquidity risk (variable APY, withdrawable anytime), tax considerations (out of scope \u2014 flag and move on).\\n5. **Match the user\'s asset.** If they hold USDC or USDsui, lead with that pool. If they hold SUI and ask about yield, surface the swap-and-save path \u2014 there is no SUI-native yield product on t2000.\\n\\n## Commands\\n\\n```bash\\n# Cross-asset APY snapshot\\nt2000 rates\\n\\n# Single-asset deep dive (e.g. USDC across every protocol that offers it)\\nt2000 rates --asset USDC\\n\\n# Your current earnings + APY (positions weighted)\\nt2000 earnings\\n\\n# Full savings summary (deposits, blended APY, projected monthly)\\nt2000 fund-status\\n\\n# Earning opportunities directory (alternative entry point)\\nt2000 earn\\n```\\n\\n## Output (`t2000 rates`)\\n\\n```\\nUSDC Save: 5.10% APY Borrow: 7.20% APY (NAVI)\\nUSDsui Save: 6.40% APY Borrow: 7.80% APY (NAVI)\\n```\\n\\nIf a pool is paused or degrading, the row shows `--` for the affected side.\\n\\n## Output (`t2000 earnings`)\\n\\n```\\nSavings:\\n $100.00 USDC on NAVI @ 5.10% APY\\n $200.00 USDsui on NAVI @ 6.40% APY\\n\\nEarned today: ~$0.06\\nEarned all time: ~$2.34\\nMonthly projected: ~$1.79\\n```\\n\\n## Decision guide for the agent\\n\\n**User says \\"best place to park USDC\\":**\\n- Lead with the higher of `USDC save APY` and `USDsui save APY`.\\n- If USDsui is higher: surface the spread, surface the swap cost (~0.05% on the USDC\u2192USDsui leg), and confirm the spread covers the swap before recommending the switch.\\n- Else: NAVI USDC save is the answer \u2014 atomic, well-trodden, lowest friction.\\n\\n**User says \\"where\'s my yield going\\":**\\n- Run `t2000 earnings` (or `yield_summary` in the engine).\\n- Surface position-by-position breakdown with the blended APY at the top.\\n- Flag any position older than 30 days where APY has dropped by >2% from initial \u2014 they may want to reconsider.\\n\\n**User says \\"I hold SUI, what\'s the best yield?\\":**\\n- t2000 does not expose a SUI-native yield product. The path is `t2000-swap` (SUI \u2192 USDC or USDsui) + `t2000-save`.\\n- Surface: net APY post-swap-fee (Cetus ~0.05% on the SUI\u2192stable leg). Confirm the user is OK losing SUI price exposure.\\n- If they want to keep SUI price exposure: tell them honestly that t2000 doesn\'t have a way to earn yield on SUI directly today. Don\'t invent one.\\n\\n**User says \\"should I borrow USDC\\":**\\n- This is a credit decision, not a yield one. Pull `t2000 rates --asset USDC` for the borrow APY, then route to `t2000-borrow` for the safety checks.\\n\\n## Engine orchestration\\n\\nThe engine\'s `rates_info` tool returns the same shape as `t2000 rates` plus protocol metadata (pool addresses, last refreshed). For multi-leg \\"compare and act\\" flows:\\n\\n1. Call `rates_info` (read, auto).\\n2. Call `yield_summary` if the user has positions (read, auto).\\n3. Compose a comparison response \u2014 surface numbers + recommendation in prose.\\n4. If the user confirms a move, hand off to the action skill (`t2000-save`, `t2000-swap`, `t2000-rebalance`).\\n\\n## What NOT to do\\n\\n- **Don\'t recommend yield-chasing.** A 0.3% APY spread between pools is not worth the swap friction + tax event for most users. Recommend a switch only when the spread > 1.0% AND the user holds the source asset already.\\n- **Don\'t quote off-platform APYs.** \\"Aave USDC on Solana is 8%\\" is not a t2000 recommendation \u2014 t2000 is Sui-native by design.\\n- **Don\'t auto-execute the rebalance.** Yield comparison is read-only. Any \\"let\'s just switch you\\" requires the user to invoke `t2000-rebalance` and confirm each leg.\\n- **Don\'t invent staking.** t2000 has no SUI staking, no vSUI minting, no liquid-staking product. If the user asks for it, be honest: \\"We don\'t support that. Closest path is swap SUI \u2192 USDC and save.\\"\\n\\n## Related skills\\n\\n- `t2000-save` \u2014 execute the save once a decision is made.\\n- `t2000-swap` \u2014 convert SUI / other tokens to a saveable stable.\\n- `t2000-rebalance` \u2014 multi-leg \\"move funds to best yield\\" plan.\\n- `t2000-borrow` \u2014 credit side of the NAVI pool."}]';
141469
141302
  cachedSkills = JSON.parse(raw);
141470
141303
  return cachedSkills;
141471
141304
  }
@@ -141553,7 +141386,7 @@ function registerPrompts(server, opts = {}) {
141553
141386
  content: {
141554
141387
  type: "text",
141555
141388
  text: [
141556
- "You are a financial advisor for a t2000 AI agent bank account on Sui.",
141389
+ "You are a financial advisor for a t2000 Agentic Wallet on Sui.",
141557
141390
  "",
141558
141391
  "STEP 1 \u2014 Render the account snapshot per the canonical skill:",
141559
141392
  "",
@@ -141588,7 +141421,7 @@ function registerPrompts(server, opts = {}) {
141588
141421
  content: {
141589
141422
  type: "text",
141590
141423
  text: [
141591
- "You are a yield optimization specialist for a t2000 AI agent bank account on Sui.",
141424
+ "You are a yield optimization specialist for a t2000 Agentic Wallet on Sui.",
141592
141425
  "",
141593
141426
  "CONTEXT (USDC-canonical save policy \u2014 from the t2000-save skill):",
141594
141427
  "",
@@ -141627,7 +141460,7 @@ function registerPrompts(server, opts = {}) {
141627
141460
  content: {
141628
141461
  type: "text",
141629
141462
  text: [
141630
- "You are a savings advisor for a t2000 AI agent bank account on Sui.",
141463
+ "You are a savings advisor for a t2000 Agentic Wallet on Sui.",
141631
141464
  "",
141632
141465
  "WHICH ASSETS CAN BE SAVED (from the t2000-save skill \u2014 canonical):",
141633
141466
  "",
@@ -141661,7 +141494,7 @@ function registerPrompts(server, opts = {}) {
141661
141494
  content: {
141662
141495
  type: "text",
141663
141496
  text: [
141664
- "You are a money-routing assistant for a t2000 AI agent bank account on Sui.",
141497
+ "You are a money-routing assistant for a t2000 Agentic Wallet on Sui.",
141665
141498
  "",
141666
141499
  "SAVE ELIGIBILITY (from the t2000-save skill):",
141667
141500
  "",
@@ -141700,7 +141533,7 @@ function registerPrompts(server, opts = {}) {
141700
141533
  content: {
141701
141534
  type: "text",
141702
141535
  text: [
141703
- "You are a risk assessment specialist for a t2000 AI agent bank account on Sui.",
141536
+ "You are a risk assessment specialist for a t2000 Agentic Wallet on Sui.",
141704
141537
  "",
141705
141538
  "STEP 1 \u2014 Read the account state (use the t2000-account-report skill's tool sequence):",
141706
141539
  "",
@@ -141744,7 +141577,7 @@ function registerPrompts(server, opts = {}) {
141744
141577
  content: {
141745
141578
  type: "text",
141746
141579
  text: [
141747
- "You are a personal finance newsletter writer for a t2000 AI agent bank account on Sui.",
141580
+ "You are a personal finance newsletter writer for a t2000 Agentic Wallet on Sui.",
141748
141581
  "",
141749
141582
  "STEP 1 \u2014 Read the account state (use the t2000-account-report tool sequence) + t2000_history (limit: 50) in parallel:",
141750
141583
  "",
@@ -141788,7 +141621,7 @@ function registerPrompts(server, opts = {}) {
141788
141621
  content: {
141789
141622
  type: "text",
141790
141623
  text: [
141791
- "You are a payment assistant for a t2000 AI agent bank account on Sui.",
141624
+ "You are a payment assistant for a t2000 Agentic Wallet on Sui.",
141792
141625
  "",
141793
141626
  context ? `Context provided by the user:
141794
141627
  ${context}
@@ -141826,7 +141659,7 @@ ${context}
141826
141659
  content: {
141827
141660
  type: "text",
141828
141661
  text: [
141829
- "You are a budget advisor for a t2000 AI agent bank account on Sui.",
141662
+ "You are a budget advisor for a t2000 Agentic Wallet on Sui.",
141830
141663
  "",
141831
141664
  amount2 ? `The user wants to know if they can afford to spend $${amount2}.` : "The user wants a general spending check.",
141832
141665
  "",
@@ -141875,7 +141708,7 @@ ${context}
141875
141708
  content: {
141876
141709
  type: "text",
141877
141710
  text: [
141878
- "You are a financial scenario planner for a t2000 AI agent bank account on Sui.",
141711
+ "You are a financial scenario planner for a t2000 Agentic Wallet on Sui.",
141879
141712
  "",
141880
141713
  scenario ? `The user wants to evaluate: "${scenario}"` : "The user wants to explore a hypothetical financial scenario. Ask them what they're considering.",
141881
141714
  "",
@@ -141926,7 +141759,7 @@ ${context}
141926
141759
  content: {
141927
141760
  type: "text",
141928
141761
  text: [
141929
- "You are a rewards management assistant for a t2000 AI agent bank account on Sui.",
141762
+ "You are a rewards management assistant for a t2000 Agentic Wallet on Sui.",
141930
141763
  "",
141931
141764
  // No dedicated claim-rewards skill — the flow is operational
141932
141765
  // enough that a thin prompt suffices. Future: if a
@@ -141969,7 +141802,7 @@ ${context}
141969
141802
  content: {
141970
141803
  type: "text",
141971
141804
  text: [
141972
- "You are a security advisor for a t2000 AI agent bank account on Sui.",
141805
+ "You are a security advisor for a t2000 Agentic Wallet on Sui.",
141973
141806
  "",
141974
141807
  "CANONICAL SAFEGUARDS REFERENCE (from the t2000-safeguards skill \u2014 full body):",
141975
141808
  "",
@@ -142004,7 +141837,7 @@ ${context}
142004
141837
  content: {
142005
141838
  type: "text",
142006
141839
  text: [
142007
- "You are a friendly onboarding guide for t2000 \u2014 an AI agent bank account on Sui.",
141840
+ "You are a friendly onboarding guide for t2000 \u2014 an Agentic Wallet on Sui.",
142008
141841
  "",
142009
141842
  "STEP 1 \u2014 Read the user's current state (t2000_overview).",
142010
141843
  "",
@@ -142052,7 +141885,7 @@ ${context}
142052
141885
  content: {
142053
141886
  type: "text",
142054
141887
  text: [
142055
- "You are an emergency response handler for a t2000 AI agent bank account on Sui.",
141888
+ "You are an emergency response handler for a t2000 Agentic Wallet on Sui.",
142056
141889
  "",
142057
141890
  "\u{1F6A8} EMERGENCY PROTOCOL",
142058
141891
  "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
@@ -142099,7 +141932,7 @@ ${context}
142099
141932
  content: {
142100
141933
  type: "text",
142101
141934
  text: [
142102
- "You are a full-account optimizer for a t2000 AI agent bank account on Sui.",
141935
+ "You are a full-account optimizer for a t2000 Agentic Wallet on Sui.",
142103
141936
  "",
142104
141937
  "STEP 1 \u2014 Read the account state in parallel: call t2000_overview AND t2000_all_rates.",
142105
141938
  " For MCP clients with canvas rendering, also use the t2000-account-report tool sequence:",
@@ -142143,7 +141976,7 @@ ${context}
142143
141976
  })
142144
141977
  );
142145
141978
  }
142146
- var PKG_VERSION = "3.1.1";
141979
+ var PKG_VERSION = "3.3.0";
142147
141980
  console.log = (...args) => console.error("[log]", ...args);
142148
141981
  console.warn = (...args) => console.error("[warn]", ...args);
142149
141982
  async function startMcpServer(opts) {
@@ -142234,4 +142067,4 @@ axios/dist/node/axios.cjs:
142234
142067
  @scure/bip39/index.js:
142235
142068
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
142236
142069
  */
142237
- //# sourceMappingURL=dist-2LJUAYXZ.js.map
142070
+ //# sourceMappingURL=dist-UDLQ4IJN.js.map