@ldgr/mcp 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ A remote MCP connection cannot install software, access local files, unlock a wa
13
13
  Node.js 20.19 or newer is required. Install the package, then create or import a wallet in your own terminal:
14
14
 
15
15
  ```sh
16
- npm install --global @ldgr/mcp@0.1.3
16
+ npm install --global @ldgr/mcp@0.1.4
17
17
  ldgr-mcp wallet create --testnet
18
18
  # Or: ldgr-mcp wallet import --testnet
19
19
  ldgr-mcp wallet list
@@ -68,6 +68,7 @@ Restart the MCP process after upgrading; a running process keeps its loaded SDK.
68
68
  | `prepare_transfer` | Unsigned transfer request |
69
69
  | `prepare_token_creation` | Unsigned fixed/mintable token creation request |
70
70
  | `prepare_escrow` | Unsigned escrow funding request |
71
+ | `prepare_swap` | Unsigned exact-input swap with an explicit positive minimum received |
71
72
  | `wallet_setup_instructions` | Exact local installation and setup commands |
72
73
  | `wallet_info` | Public selected-wallet metadata, local stdio only |
73
74
 
@@ -104,6 +105,26 @@ npx --yes --package @ldgr/mcp@latest ldgr-mcp approve <request-file>
104
105
 
105
106
  The CLI validates the request and selected network, resolves fresh asset precision, checks the ledger's current fees and nonces, and presents the transaction for explicit local approval. Do not run approval unattended. Prepared requests may become invalid as balances, fees, configuration, or deadlines change. Reconcile an uncertain submission before trying again.
106
107
 
108
+ ## Swaps
109
+
110
+ MCP 0.1.4 adds `prepare_swap`; approving these requests requires CLI 0.5.2 or
111
+ newer. First use `get_swap_quote` for a non-binding quote. Then prepare an intent
112
+ with explicit `network`, `assetIn`, `assetOut`, `amountIn`, and `amountOutMin`.
113
+ Both amounts are positive decimal strings in their respective asset's display
114
+ units. `maxHops` is optional, accepts 1, 2, or 3, and defaults to 3. Native aliases
115
+ `t0`/`t1` resolve to `dng` for the selected network. Identical assets and zero
116
+ minimum output are rejected.
117
+
118
+ Preparation does not select a route or execute a swap. During `approve`, the
119
+ CLI fetches a fresh route, checks the input balance and native fee balance, and
120
+ shows the route, quote, exact input and minimum received. Output returns to the
121
+ selected wallet. The reviewed route and minimum are signed unchanged; the CLI
122
+ never lowers the minimum to make a quote executable. Pool fees are included in
123
+ the quote, while one additional native network fee is charged. Route swaps use
124
+ the `dng` nonce even when swapping between two tokens. The portable request's
125
+ expiry governs local approval; the existing protocol timestamp rules govern
126
+ signed submission validity.
127
+
107
128
  ## Embedding
108
129
 
109
130
  ```ts
package/dist/cli.js CHANGED
@@ -249,7 +249,7 @@ class AssetMismatchError extends Error {
249
249
  class WalletNetworkMismatchError extends Error {
250
250
  }
251
251
  function createLdgrMcpServer(options = {}) {
252
- const server = new McpServer({ name: "ldgr", version: "0.1.3" }, { instructions: INSTRUCTIONS });
252
+ const server = new McpServer({ name: "ldgr", version: "0.1.4" }, { instructions: INSTRUCTIONS });
253
253
  const request = readTransport(options.fetch);
254
254
  const now = options.now ?? Date.now;
255
255
  const envelope = (network, source, data) => ({ network, source, data });
@@ -349,12 +349,27 @@ function createLdgrMcpServer(options = {}) {
349
349
  const a = exactAsset(args.assetA, args.network), b = exactAsset(args.assetB, args.network), client = await checkedClient(args.network, request);
350
350
  return envelope(args.network, "ledger", await client.amm.getPoolByPair(a, b));
351
351
  });
352
- tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Does not prepare, sign or submit a swap.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
352
+ tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Use prepare_swap with an explicit positive minimum received to prepare an unsigned intent; only human CLI approval can execute it.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
353
353
  const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
354
354
  checkNativeAmount(assetIn, args.amountIn, args.network);
355
355
  const client = await checkedClient(args.network, request);
356
356
  return envelope(args.network, "ledger", await client.amm.quoteRoute(assetIn, assetOut, args.amountIn, 3));
357
357
  });
358
+ tool("prepare_swap", "Prepare an unsigned exact-input swap for human CLI approval. Specify both assets, amountIn and a positive amountOutMin in decimal display units. The CLI fetches a fresh route of up to maxHops pools and shows it before signing; it never lowers the minimum. Output goes to the selected wallet. Preparation does not quote, unlock, sign or submit.", {
359
+ network: networkSchema,
360
+ assetIn: assetSchema,
361
+ assetOut: assetSchema,
362
+ amountIn: positiveDecimalSchema,
363
+ amountOutMin: positiveDecimalSchema,
364
+ maxHops: z2.number().int().min(1).max(3).default(3)
365
+ }, async (args) => {
366
+ const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
367
+ if (assetIn === assetOut)
368
+ throw new Error("Swap assets must differ");
369
+ checkNativeAmount(assetIn, args.amountIn, args.network);
370
+ checkNativeAmount(assetOut, args.amountOutMin, args.network);
371
+ return prepared(unsignedRequest(args.network, "swap", { assetIn, assetOut, amountIn: args.amountIn, amountOutMin: args.amountOutMin, maxHops: args.maxHops }, now()));
372
+ }, false);
358
373
  tool("prepare_transfer", "Prepare an unsigned transfer for human review in the local CLI wallet. Does not unlock, sign or submit.", { network: networkSchema, to: addressSchema, asset: assetSchema, amount: positiveDecimalSchema, memo: referenceSchema.optional() }, async (args) => {
359
374
  const to = addressForNetwork(args.to, args.network), asset = exactAsset(args.asset, args.network);
360
375
  checkNativeAmount(asset, args.amount, args.network);
@@ -398,7 +413,7 @@ function createLdgrMcpServer(options = {}) {
398
413
  }, false);
399
414
  tool("wallet_setup_instructions", "Explain user-run CLI wallet installation, creation/import and MCP connection. This tool cannot install software or access local files.", { network: networkSchema }, async (args) => ({
400
415
  network: args.network,
401
- install: "npm install --global @ldgr/mcp@0.1.3",
416
+ install: "npm install --global @ldgr/mcp@0.1.4",
402
417
  node: ">=20.19.0",
403
418
  create: `ldgr-mcp wallet create${args.network === "testnet" ? " --testnet" : ""}`,
404
419
  import: `ldgr-mcp wallet import${args.network === "testnet" ? " --testnet" : ""}`,
@@ -477,7 +492,7 @@ async function startLdgrMcpStdio(options = {}) {
477
492
  }
478
493
 
479
494
  // src/cli.ts
480
- var HELP = `LDGR MCP 0.1.3
495
+ var HELP = `LDGR MCP 0.1.4
481
496
 
482
497
  ldgr-mcp Start local MCP over stdio
483
498
  ldgr-mcp --wallet <path> Start MCP with a selected wallet store
package/dist/index.js CHANGED
@@ -121,7 +121,7 @@ class AssetMismatchError extends Error {
121
121
  class WalletNetworkMismatchError extends Error {
122
122
  }
123
123
  function createLdgrMcpServer(options = {}) {
124
- const server = new McpServer({ name: "ldgr", version: "0.1.3" }, { instructions: INSTRUCTIONS });
124
+ const server = new McpServer({ name: "ldgr", version: "0.1.4" }, { instructions: INSTRUCTIONS });
125
125
  const request = readTransport(options.fetch);
126
126
  const now = options.now ?? Date.now;
127
127
  const envelope = (network, source, data) => ({ network, source, data });
@@ -221,12 +221,27 @@ function createLdgrMcpServer(options = {}) {
221
221
  const a = exactAsset(args.assetA, args.network), b = exactAsset(args.assetB, args.network), client = await checkedClient(args.network, request);
222
222
  return envelope(args.network, "ledger", await client.amm.getPoolByPair(a, b));
223
223
  });
224
- tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Does not prepare, sign or submit a swap.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
224
+ tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Use prepare_swap with an explicit positive minimum received to prepare an unsigned intent; only human CLI approval can execute it.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
225
225
  const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
226
226
  checkNativeAmount(assetIn, args.amountIn, args.network);
227
227
  const client = await checkedClient(args.network, request);
228
228
  return envelope(args.network, "ledger", await client.amm.quoteRoute(assetIn, assetOut, args.amountIn, 3));
229
229
  });
230
+ tool("prepare_swap", "Prepare an unsigned exact-input swap for human CLI approval. Specify both assets, amountIn and a positive amountOutMin in decimal display units. The CLI fetches a fresh route of up to maxHops pools and shows it before signing; it never lowers the minimum. Output goes to the selected wallet. Preparation does not quote, unlock, sign or submit.", {
231
+ network: networkSchema,
232
+ assetIn: assetSchema,
233
+ assetOut: assetSchema,
234
+ amountIn: positiveDecimalSchema,
235
+ amountOutMin: positiveDecimalSchema,
236
+ maxHops: z2.number().int().min(1).max(3).default(3)
237
+ }, async (args) => {
238
+ const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
239
+ if (assetIn === assetOut)
240
+ throw new Error("Swap assets must differ");
241
+ checkNativeAmount(assetIn, args.amountIn, args.network);
242
+ checkNativeAmount(assetOut, args.amountOutMin, args.network);
243
+ return prepared(unsignedRequest(args.network, "swap", { assetIn, assetOut, amountIn: args.amountIn, amountOutMin: args.amountOutMin, maxHops: args.maxHops }, now()));
244
+ }, false);
230
245
  tool("prepare_transfer", "Prepare an unsigned transfer for human review in the local CLI wallet. Does not unlock, sign or submit.", { network: networkSchema, to: addressSchema, asset: assetSchema, amount: positiveDecimalSchema, memo: referenceSchema.optional() }, async (args) => {
231
246
  const to = addressForNetwork(args.to, args.network), asset = exactAsset(args.asset, args.network);
232
247
  checkNativeAmount(asset, args.amount, args.network);
@@ -270,7 +285,7 @@ function createLdgrMcpServer(options = {}) {
270
285
  }, false);
271
286
  tool("wallet_setup_instructions", "Explain user-run CLI wallet installation, creation/import and MCP connection. This tool cannot install software or access local files.", { network: networkSchema }, async (args) => ({
272
287
  network: args.network,
273
- install: "npm install --global @ldgr/mcp@0.1.3",
288
+ install: "npm install --global @ldgr/mcp@0.1.4",
274
289
  node: ">=20.19.0",
275
290
  create: `ldgr-mcp wallet create${args.network === "testnet" ? " --testnet" : ""}`,
276
291
  import: `ldgr-mcp wallet import${args.network === "testnet" ? " --testnet" : ""}`,
@@ -5,7 +5,7 @@ export type UnsignedMcpRequest = {
5
5
  readonly requestId: string;
6
6
  readonly network: McpNetwork;
7
7
  readonly expiresAt: string;
8
- readonly action: "transfer" | "create_token" | "open_escrow";
8
+ readonly action: "transfer" | "create_token" | "open_escrow" | "swap";
9
9
  readonly params: Readonly<Record<string, string | number | undefined>>;
10
10
  };
11
11
  export declare const networkSchema: z.ZodEnum<{
package/dist/stdio.js CHANGED
@@ -247,7 +247,7 @@ class AssetMismatchError extends Error {
247
247
  class WalletNetworkMismatchError extends Error {
248
248
  }
249
249
  function createLdgrMcpServer(options = {}) {
250
- const server = new McpServer({ name: "ldgr", version: "0.1.3" }, { instructions: INSTRUCTIONS });
250
+ const server = new McpServer({ name: "ldgr", version: "0.1.4" }, { instructions: INSTRUCTIONS });
251
251
  const request = readTransport(options.fetch);
252
252
  const now = options.now ?? Date.now;
253
253
  const envelope = (network, source, data) => ({ network, source, data });
@@ -347,12 +347,27 @@ function createLdgrMcpServer(options = {}) {
347
347
  const a = exactAsset(args.assetA, args.network), b = exactAsset(args.assetB, args.network), client = await checkedClient(args.network, request);
348
348
  return envelope(args.network, "ledger", await client.amm.getPoolByPair(a, b));
349
349
  });
350
- tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Does not prepare, sign or submit a swap.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
350
+ tool("get_swap_quote", "Read a non-binding swap quote for explicit input/output assets. Use prepare_swap with an explicit positive minimum received to prepare an unsigned intent; only human CLI approval can execute it.", { network: networkSchema, assetIn: assetSchema, assetOut: assetSchema, amountIn: positiveDecimalSchema }, async (args) => {
351
351
  const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
352
352
  checkNativeAmount(assetIn, args.amountIn, args.network);
353
353
  const client = await checkedClient(args.network, request);
354
354
  return envelope(args.network, "ledger", await client.amm.quoteRoute(assetIn, assetOut, args.amountIn, 3));
355
355
  });
356
+ tool("prepare_swap", "Prepare an unsigned exact-input swap for human CLI approval. Specify both assets, amountIn and a positive amountOutMin in decimal display units. The CLI fetches a fresh route of up to maxHops pools and shows it before signing; it never lowers the minimum. Output goes to the selected wallet. Preparation does not quote, unlock, sign or submit.", {
357
+ network: networkSchema,
358
+ assetIn: assetSchema,
359
+ assetOut: assetSchema,
360
+ amountIn: positiveDecimalSchema,
361
+ amountOutMin: positiveDecimalSchema,
362
+ maxHops: z2.number().int().min(1).max(3).default(3)
363
+ }, async (args) => {
364
+ const assetIn = exactAsset(args.assetIn, args.network), assetOut = exactAsset(args.assetOut, args.network);
365
+ if (assetIn === assetOut)
366
+ throw new Error("Swap assets must differ");
367
+ checkNativeAmount(assetIn, args.amountIn, args.network);
368
+ checkNativeAmount(assetOut, args.amountOutMin, args.network);
369
+ return prepared(unsignedRequest(args.network, "swap", { assetIn, assetOut, amountIn: args.amountIn, amountOutMin: args.amountOutMin, maxHops: args.maxHops }, now()));
370
+ }, false);
356
371
  tool("prepare_transfer", "Prepare an unsigned transfer for human review in the local CLI wallet. Does not unlock, sign or submit.", { network: networkSchema, to: addressSchema, asset: assetSchema, amount: positiveDecimalSchema, memo: referenceSchema.optional() }, async (args) => {
357
372
  const to = addressForNetwork(args.to, args.network), asset = exactAsset(args.asset, args.network);
358
373
  checkNativeAmount(asset, args.amount, args.network);
@@ -396,7 +411,7 @@ function createLdgrMcpServer(options = {}) {
396
411
  }, false);
397
412
  tool("wallet_setup_instructions", "Explain user-run CLI wallet installation, creation/import and MCP connection. This tool cannot install software or access local files.", { network: networkSchema }, async (args) => ({
398
413
  network: args.network,
399
- install: "npm install --global @ldgr/mcp@0.1.3",
414
+ install: "npm install --global @ldgr/mcp@0.1.4",
400
415
  node: ">=20.19.0",
401
416
  create: `ldgr-mcp wallet create${args.network === "testnet" ? " --testnet" : ""}`,
402
417
  import: `ldgr-mcp wallet import${args.network === "testnet" ? " --testnet" : ""}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ldgr/mcp",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {