@cmdoss/suipay-mcp 0.2.2-dev.1 → 0.2.2-dev.3

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
@@ -76,8 +76,13 @@ json: {"prompt":"a cat"}
76
76
  maxAmount: 50000
77
77
  ```
78
78
 
79
- `pay` uses SDK `createPayer` internally. A delivered image is returned as an MCP
80
- image block, not as a base64 wall in the JSON summary.
79
+ `pay` uses SDK `createPayer` internally. A binary body is written once under
80
+ `~/.suipay/deliveries/` and named first in the JSON as `savedTo` (absolute
81
+ path) and `savedToUrl` (`file://`). Any MIME — image, audio, pdf,
82
+ octet-stream. JSON stays compact (no base64 wall). An MCP `image` block is an
83
+ extra display hint when the type is `image/*`; hosts such as Claude Code's
84
+ TUI may not render it. Always quote `savedTo` to the user. Do not call `pay`
85
+ again to "save" a delivery that already settled.
81
86
 
82
87
  ## Targets
83
88
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "../chunk-K6WM4Z7H.js";
5
- import "../chunk-NVTYOOMY.js";
4
+ } from "../chunk-C2IYSV43.js";
5
+ import "../chunk-SRMAH6MK.js";
6
6
 
7
7
  // src/bin/suipay.ts
8
8
  main().catch((err) => {
@@ -4,7 +4,7 @@ import {
4
4
  loadLocalSigningKeyRecord,
5
5
  loadMcpConfig,
6
6
  loadPaymentProfile
7
- } from "./chunk-NVTYOOMY.js";
7
+ } from "./chunk-SRMAH6MK.js";
8
8
 
9
9
  // src/index.ts
10
10
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -6872,6 +6872,52 @@ function joinDiscoverCatalog(opts) {
6872
6872
  return scoped ? { accessMode: "scoped", count: services.length, services, allowedTargetHashes } : { accessMode: "open", count: services.length, services };
6873
6873
  }
6874
6874
 
6875
+ // src/tool-result.ts
6876
+ import { pathToFileURL } from "url";
6877
+
6878
+ // src/delivery-file.ts
6879
+ import { mkdirSync as mkdirSync2, writeFileSync, chmodSync as chmodSync2 } from "fs";
6880
+ import { dirname as dirname2, join as join3 } from "path";
6881
+ function mcpDeliveriesDir() {
6882
+ return join3(dirname2(mcpCredentialsPath()), "deliveries");
6883
+ }
6884
+ var EXT = {
6885
+ "image/png": ".png",
6886
+ "image/jpeg": ".jpg",
6887
+ "image/jpg": ".jpg",
6888
+ "image/webp": ".webp",
6889
+ "image/gif": ".gif",
6890
+ "image/svg+xml": ".svg",
6891
+ "audio/mpeg": ".mp3",
6892
+ "audio/wav": ".wav",
6893
+ "audio/ogg": ".ogg",
6894
+ "video/mp4": ".mp4",
6895
+ "application/pdf": ".pdf",
6896
+ "application/json": ".json",
6897
+ "text/plain": ".txt"
6898
+ };
6899
+ function extensionFor(contentType) {
6900
+ const type = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
6901
+ return EXT[type] ?? ".bin";
6902
+ }
6903
+ function fileStem(digest, challengeId) {
6904
+ const raw = (digest ?? challengeId ?? `delivery-${Date.now()}`).trim();
6905
+ const safe = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
6906
+ return (safe.slice(0, 80) || `delivery-${Date.now()}`).replace(/^\.+$/, "delivery");
6907
+ }
6908
+ function saveDeliveredBody(input) {
6909
+ if (input.bytes.byteLength === 0) return void 0;
6910
+ const dir = mcpDeliveriesDir();
6911
+ mkdirSync2(dir, { recursive: true, mode: 448 });
6912
+ const path = join3(
6913
+ dir,
6914
+ `${fileStem(input.digest, input.challengeId)}${extensionFor(input.contentType)}`
6915
+ );
6916
+ writeFileSync(path, input.bytes, { mode: 384 });
6917
+ chmodSync2(path, 384);
6918
+ return path;
6919
+ }
6920
+
6875
6921
  // src/tool-result.ts
6876
6922
  var MAX_MCP_IMAGE_BYTES = 5 * 1024 * 1024;
6877
6923
  function text(value) {
@@ -6893,6 +6939,11 @@ function closedError(code, detail) {
6893
6939
  function closedPayError(code, detail) {
6894
6940
  return error({ status: "failed", paid: false, code, detail });
6895
6941
  }
6942
+ function receiptChallengeId(receipt) {
6943
+ if (!receipt || typeof receipt !== "object") return void 0;
6944
+ const id = receipt.challengeId;
6945
+ return typeof id === "string" && id.length > 0 ? id : void 0;
6946
+ }
6896
6947
  function paidResult(result) {
6897
6948
  if (!isBinaryBody(result.body)) return text(result);
6898
6949
  const body = result.body;
@@ -6901,8 +6952,28 @@ function paidResult(result) {
6901
6952
  contentType: body.contentType,
6902
6953
  byteLength: body.byteLength
6903
6954
  };
6955
+ let savedTo;
6956
+ try {
6957
+ savedTo = saveDeliveredBody({
6958
+ bytes: body.bytes,
6959
+ contentType: body.contentType,
6960
+ digest: result.txDigest,
6961
+ challengeId: receiptChallengeId(result.receipt)
6962
+ });
6963
+ } catch {
6964
+ savedTo = void 0;
6965
+ }
6966
+ const payload = savedTo ? {
6967
+ savedTo,
6968
+ savedToUrl: pathToFileURL(savedTo).href,
6969
+ ...result,
6970
+ body: shape
6971
+ } : { ...result, body: shape };
6904
6972
  const content = [
6905
- { type: "text", text: JSON.stringify({ ...result, body: shape }, null, 2) }
6973
+ {
6974
+ type: "text",
6975
+ text: JSON.stringify(payload, null, 2)
6976
+ }
6906
6977
  ];
6907
6978
  if (body.contentType.startsWith("image/") && body.bytes.byteLength > 0 && body.bytes.byteLength <= MAX_MCP_IMAGE_BYTES) {
6908
6979
  content.push({
@@ -7526,7 +7597,7 @@ var TOOLS = [
7526
7597
  },
7527
7598
  {
7528
7599
  name: "pay",
7529
- description: "Pay a HTTP resource via delegate. On hosted /mcp the gateway PREPARES an unsigned transaction and returns it (prepare-only \u2014 it never holds the delegate key and cannot settle). Only a process holding the delegate key the grant names can complete settlement (e.g. local stdio MCP, or any self-hosted process with the matching key). Pass recipient and/or maxAmount to state who you intend to pay and what you will spend; both are checked before anything is signed or handed back. Local V1 allowance pay is retired.",
7600
+ description: "Pay a HTTP resource via delegate. On hosted /mcp the gateway PREPARES an unsigned transaction and returns it (prepare-only \u2014 it never holds the delegate key and cannot settle). Only a process holding the delegate key the grant names can complete settlement (e.g. local stdio MCP, or any self-hosted process with the matching key). Pass recipient and/or maxAmount to state who you intend to pay and what you will spend; both are checked before anything is signed or handed back. Local V1 allowance pay is retired. A paid binary body is written under ~/.suipay/deliveries/ and named as savedTo (absolute path) and savedToUrl (file://) at the top of the JSON. Always quote savedTo to the user so they can open the file. Do not assume the host rendered an image block. Never call pay again to display or save a delivery that already settled.",
7530
7601
  inputSchema: {
7531
7602
  type: "object",
7532
7603
  properties: {
package/dist/http.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleSuipayMcpHttpRequest
3
- } from "./chunk-NVTYOOMY.js";
3
+ } from "./chunk-SRMAH6MK.js";
4
4
  export {
5
5
  handleSuipayMcpHttpRequest
6
6
  };
package/dist/index.d.ts CHANGED
@@ -340,11 +340,6 @@ interface StartedStdioLogin {
340
340
  */
341
341
  declare function startStdioLogin(opts: StdioLoginOptions): Promise<StartedStdioLogin>;
342
342
 
343
- /**
344
- * MCP tool payloads. Settlement honesty matches the playground stamp:
345
- * money that moved is never reported as a tool error (that invites a second pay).
346
- */
347
-
348
343
  type ToolResult = CallToolResult;
349
344
 
350
345
  interface ToolDeps {
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadBootProfile,
3
3
  main
4
- } from "./chunk-K6WM4Z7H.js";
4
+ } from "./chunk-C2IYSV43.js";
5
5
  import {
6
6
  MCP_TARGET_PRESETS,
7
7
  PACKAGE_NAME,
@@ -26,7 +26,7 @@ import {
26
26
  settlePreparedMcpPayment,
27
27
  traceMcpHttpRequest,
28
28
  verifySpendAccountPayReconstructs
29
- } from "./chunk-NVTYOOMY.js";
29
+ } from "./chunk-SRMAH6MK.js";
30
30
  export {
31
31
  MCP_TARGET_PRESETS,
32
32
  PACKAGE_NAME,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmdoss/suipay-mcp",
3
- "version": "0.2.2-dev.1",
3
+ "version": "0.2.2-dev.3",
4
4
  "type": "module",
5
5
  "description": "SuiPay MCP — pay MPP-gated APIs from a spend-account grant with an agent-held delegate key.",
6
6
  "main": "./dist/index.js",