@cmdoss/suipay-mcp 0.2.2-dev.5 → 0.2.2-dev.6

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
@@ -51,7 +51,7 @@ missing, expired, or revoked.
51
51
  | Tool | Purpose |
52
52
  | --- | --- |
53
53
  | `discover` | Search live gateway resources. After login: `name`, `path`, `url`, `targetHash`, catalog price, and `affordable` (can this session cover one call — not authorization). `pay({ url })` still settles |
54
- | `pay` | Fetch resource, prepare `spend_account` settlement, settle when this process holds the grant key |
54
+ | `pay` | Fetch resource, prepare `spend_account` settlement, settle when this process holds the grant key. POST `json` is the paid body. Optional stdio `file` + `fileField` fill one JSON key from a local file as canonical base64 (Walrus `contentBase64`); requires `SUIPAY_MCP_FILE_ROOT`; hosted `/mcp` refuses `file` |
55
55
  | `receipts` | List settlement receipts, optionally by challenge ID |
56
56
  | `access_context` | Report current session / delegate / policy state (no secret material) |
57
57
  | `suipay_login` | Mint or reuse the local delegate key and return a clickable console URL (does not wait for the wallet). Default target is Railway suipay-dev; pass `target: "local"` for the laptop stack |
@@ -76,6 +76,22 @@ json: {"prompt":"a cat"}
76
76
  maxAmount: 50000
77
77
  ```
78
78
 
79
+ To store local bytes (Walrus), do not paste base64. Name the file and field.
80
+ Set `SUIPAY_MCP_FILE_ROOT` to an absolute directory; `file` must resolve inside
81
+ it (unset disables attach). Paths under `~/.suipay` are refused even if that
82
+ directory falls inside the root.
83
+
84
+ ```
85
+ Pay this SuiPay resource with the suipay MCP `pay` tool. Do not write SDK code.
86
+
87
+ url: https://gateway.example/v1/walrus/store
88
+ method: POST
89
+ json: {"contentType":"text/plain"}
90
+ file: /absolute/path/to/note.txt
91
+ fileField: contentBase64
92
+ maxAmount: 50000
93
+ ```
94
+
79
95
  `pay` uses SDK `createPayer` internally. When this process settles, a binary
80
96
  body is written once under `~/.suipay/deliveries/` and named first in the
81
97
  JSON as `savedTo` (absolute path) and `savedToUrl` (`file://`). Hosted `/mcp`
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "../chunk-P54ZYBPN.js";
5
- import "../chunk-THLDEMGS.js";
4
+ } from "../chunk-AEV6Q6JC.js";
5
+ import "../chunk-UTKVBAEZ.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-THLDEMGS.js";
7
+ } from "./chunk-UTKVBAEZ.js";
8
8
 
9
9
  // src/index.ts
10
10
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -19,7 +19,7 @@ async function main() {
19
19
  const argv = process.argv.slice(2);
20
20
  const cfg = loadMcpConfig(process.env, argv);
21
21
  const target = cfg.target ?? "dev";
22
- const server = createServer(cfg);
22
+ const server = createServer(cfg, void 0, void 0, { transport: "stdio" });
23
23
  await server.connect(new StdioServerTransport());
24
24
  try {
25
25
  const boundGateway = loadLocalSigningKeyRecord()?.gatewayUrl ?? cfg.gatewayUrl;
@@ -7002,6 +7002,205 @@ function settlePayResult(result) {
7002
7002
  return error(result);
7003
7003
  }
7004
7004
 
7005
+ // src/pay-file.ts
7006
+ import { isAbsolute, dirname as dirname3, sep } from "path";
7007
+ import {
7008
+ openSync as openSync2,
7009
+ closeSync as closeSync2,
7010
+ fstatSync,
7011
+ readFileSync as readFileSync2,
7012
+ realpathSync,
7013
+ constants
7014
+ } from "fs";
7015
+ var JSON_WRAP_SLACK_BYTES = 256;
7016
+ var MCP_MAX_FILE_FIELD_BYTES = Math.floor(
7017
+ (MAX_PAID_BODY_BYTES - JSON_WRAP_SLACK_BYTES) * 3 / 4
7018
+ );
7019
+ var FIELD = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
7020
+ var FORBIDDEN = /* @__PURE__ */ new Set(["constructor", "prototype"]);
7021
+ function fail2(code, detail) {
7022
+ return { code, detail };
7023
+ }
7024
+ function hasLocalFileArgs(input) {
7025
+ return input.file !== void 0 && input.file !== null || input.fileField !== void 0 && input.fileField !== null;
7026
+ }
7027
+ function parseField(value) {
7028
+ if (typeof value !== "string" || !FIELD.test(value) || FORBIDDEN.has(value)) {
7029
+ return fail2("INVALID_FILE_FIELD", "fileField must be a simple JSON key");
7030
+ }
7031
+ return value;
7032
+ }
7033
+ function parsePath(value) {
7034
+ if (typeof value !== "string" || value.length === 0 || value.includes("\0")) {
7035
+ return fail2("INVALID_FILE", "file must be a non-empty absolute path");
7036
+ }
7037
+ if (!isAbsolute(value) || value.includes("://")) {
7038
+ return fail2("INVALID_FILE", "file must be an absolute filesystem path, not a URL");
7039
+ }
7040
+ return value;
7041
+ }
7042
+ function parseMethod(value) {
7043
+ if (value === void 0 || value === null) return "GET";
7044
+ if (typeof value !== "string") {
7045
+ return fail2("MALFORMED_REQUEST", "method must be GET or POST");
7046
+ }
7047
+ const upper = value.trim().toUpperCase();
7048
+ if (upper === "GET" || upper === "POST") return upper;
7049
+ return fail2("MALFORMED_REQUEST", "method must be GET or POST");
7050
+ }
7051
+ function inside(root, candidate) {
7052
+ const prefix = root.endsWith(sep) ? root : root + sep;
7053
+ return candidate === root || candidate.startsWith(prefix);
7054
+ }
7055
+ function resolveContainedPath(raw) {
7056
+ const rootRaw = process.env.SUIPAY_MCP_FILE_ROOT;
7057
+ if (typeof rootRaw !== "string" || rootRaw.trim() === "") {
7058
+ return fail2(
7059
+ "FILE_ROOT_UNSET",
7060
+ "file attach requires SUIPAY_MCP_FILE_ROOT to be an absolute directory"
7061
+ );
7062
+ }
7063
+ if (!isAbsolute(rootRaw) || rootRaw.includes("://")) {
7064
+ return fail2(
7065
+ "FILE_ROOT_UNSET",
7066
+ "SUIPAY_MCP_FILE_ROOT must be an absolute filesystem path"
7067
+ );
7068
+ }
7069
+ let rootReal;
7070
+ let fileReal;
7071
+ try {
7072
+ rootReal = realpathSync(rootRaw);
7073
+ } catch {
7074
+ return fail2("FILE_ROOT_UNSET", "SUIPAY_MCP_FILE_ROOT is not a readable directory");
7075
+ }
7076
+ try {
7077
+ fileReal = realpathSync(raw);
7078
+ } catch (err) {
7079
+ const code = err.code;
7080
+ if (code === "ENOENT" || code === "ENOTDIR") {
7081
+ return fail2("FILE_NOT_FOUND", "file does not exist");
7082
+ }
7083
+ if (code === "EACCES") {
7084
+ return fail2("FILE_EACCES", "file is not readable");
7085
+ }
7086
+ return fail2(
7087
+ "INVALID_FILE",
7088
+ `file could not be read (${code ?? "unknown error"})`
7089
+ );
7090
+ }
7091
+ if (!inside(rootReal, fileReal)) {
7092
+ return fail2("FILE_OUTSIDE_ROOT", "file must be under SUIPAY_MCP_FILE_ROOT");
7093
+ }
7094
+ const credsDir2 = dirname3(mcpCredentialsPath());
7095
+ let credsReal = credsDir2;
7096
+ try {
7097
+ credsReal = realpathSync(credsDir2);
7098
+ } catch {
7099
+ }
7100
+ if (inside(credsReal, fileReal)) {
7101
+ return fail2("FILE_FORBIDDEN", "file must not be under ~/.suipay");
7102
+ }
7103
+ return fileReal;
7104
+ }
7105
+ function readRegularFile(path) {
7106
+ if (constants.O_NOFOLLOW === void 0 || constants.O_NONBLOCK === void 0) {
7107
+ return fail2("INVALID_FILE", "symlink-safe nonblocking open is unavailable on this platform");
7108
+ }
7109
+ let fd;
7110
+ try {
7111
+ const flags = constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK;
7112
+ fd = openSync2(path, flags);
7113
+ const st = fstatSync(fd);
7114
+ if (!st.isFile()) {
7115
+ return fail2("INVALID_FILE", "file must be a regular file");
7116
+ }
7117
+ if (st.size > MCP_MAX_FILE_FIELD_BYTES) {
7118
+ return fail2(
7119
+ "FILE_TOO_LARGE",
7120
+ `file is ${st.size} bytes; exceeds ${MCP_MAX_FILE_FIELD_BYTES} decoded bytes`
7121
+ );
7122
+ }
7123
+ const bytes = readFileSync2(fd);
7124
+ if (bytes.byteLength === 0) {
7125
+ return fail2("EMPTY_FILE", "file is empty");
7126
+ }
7127
+ if (bytes.byteLength > MCP_MAX_FILE_FIELD_BYTES) {
7128
+ return fail2(
7129
+ "FILE_TOO_LARGE",
7130
+ `file is ${bytes.byteLength} bytes; exceeds ${MCP_MAX_FILE_FIELD_BYTES} decoded bytes`
7131
+ );
7132
+ }
7133
+ return bytes;
7134
+ } catch (err) {
7135
+ const code = err.code;
7136
+ if (code === "ENOENT" || code === "ENOTDIR") {
7137
+ return fail2("FILE_NOT_FOUND", "file does not exist");
7138
+ }
7139
+ if (code === "ELOOP" || code === "EMLINK" || code === "ENXIO") {
7140
+ return fail2("INVALID_FILE", "file must be a regular file");
7141
+ }
7142
+ if (code === "EACCES") return fail2("FILE_EACCES", "file is not readable");
7143
+ return fail2(
7144
+ "INVALID_FILE",
7145
+ `file could not be read (${code ?? "unknown error"})`
7146
+ );
7147
+ } finally {
7148
+ if (fd !== void 0) {
7149
+ try {
7150
+ closeSync2(fd);
7151
+ } catch {
7152
+ }
7153
+ }
7154
+ }
7155
+ }
7156
+ function toCanonicalBase64(bytes) {
7157
+ return Buffer.from(bytes).toString("base64");
7158
+ }
7159
+ function jsonWithLocalFile(input) {
7160
+ const hasFile = input.file !== void 0 && input.file !== null;
7161
+ const hasField = input.fileField !== void 0 && input.fileField !== null;
7162
+ if (!hasFile && !hasField) return { json: input.json };
7163
+ if (hasFile !== hasField) {
7164
+ return {
7165
+ error: fail2(
7166
+ "INVALID_FILE_ARGS",
7167
+ "file and fileField are required together"
7168
+ )
7169
+ };
7170
+ }
7171
+ const method = parseMethod(input.method);
7172
+ if (typeof method !== "string") return { error: method };
7173
+ if (method !== "POST") {
7174
+ return { error: fail2("INVALID_FILE_ARGS", "file is only valid on POST") };
7175
+ }
7176
+ const field = parseField(input.fileField);
7177
+ if (typeof field !== "string") return { error: field };
7178
+ const path = parsePath(input.file);
7179
+ if (typeof path !== "string") return { error: path };
7180
+ let json;
7181
+ if (input.json === void 0) {
7182
+ json = {};
7183
+ } else if (typeof input.json === "object" && input.json !== null && !Array.isArray(input.json)) {
7184
+ json = { ...input.json };
7185
+ } else {
7186
+ return { error: fail2("MALFORMED_REQUEST", "POST requires json object") };
7187
+ }
7188
+ if (Object.prototype.hasOwnProperty.call(json, field)) {
7189
+ return {
7190
+ error: fail2(
7191
+ "FILE_FIELD_EXISTS",
7192
+ "json already has fileField; refuse to overwrite"
7193
+ )
7194
+ };
7195
+ }
7196
+ const contained = resolveContainedPath(path);
7197
+ if (typeof contained !== "string") return { error: contained };
7198
+ const bytes = readRegularFile(contained);
7199
+ if (!(bytes instanceof Uint8Array)) return { error: bytes };
7200
+ json[field] = toCanonicalBase64(bytes);
7201
+ return { json };
7202
+ }
7203
+
7005
7204
  // src/tools.ts
7006
7205
  function payerTrace(deps) {
7007
7206
  const hooks = deps.trace;
@@ -7080,18 +7279,34 @@ function intentViolation(intent, prepared) {
7080
7279
  }
7081
7280
  async function pay(args, cfg, deps = {}) {
7082
7281
  if (!args.url) return error("url is required");
7282
+ if (hasLocalFileArgs(args) && deps.transport === "http") {
7283
+ return closedPayError(
7284
+ "FILE_STDIO_ONLY",
7285
+ "file is stdio only; hosted /mcp does not read the buyer disk"
7286
+ );
7287
+ }
7083
7288
  let intent;
7084
7289
  try {
7085
7290
  intent = normalizePayIntent(args);
7086
7291
  } catch {
7087
7292
  return closedPayError("INVALID_INTENT", "payment intent is invalid");
7088
7293
  }
7294
+ let attached;
7295
+ try {
7296
+ attached = jsonWithLocalFile(args);
7297
+ } catch {
7298
+ return closedPayError("INVALID_FILE", "file could not be read");
7299
+ }
7300
+ if ("error" in attached) {
7301
+ return closedPayError(attached.error.code, attached.error.detail);
7302
+ }
7303
+ const paidArgs = { ...args, json: attached.json };
7089
7304
  let request;
7090
7305
  try {
7091
- request = normalizeMcpPaidHttpRequest(args);
7306
+ request = normalizeMcpPaidHttpRequest(paidArgs);
7092
7307
  } catch (err) {
7093
7308
  const raw = err instanceof Error ? err.message : "";
7094
- const detail = /method/i.test(raw) ? "method must be GET or POST" : /json/i.test(raw) ? "POST requires json" : "request could not be normalized";
7309
+ const detail = /too large/i.test(raw) ? `paid request body exceeds ${MAX_PAID_BODY_BYTES} bytes` : /method/i.test(raw) ? "method must be GET or POST" : /json/i.test(raw) ? "POST requires json" : "request could not be normalized";
7095
7310
  return closedPayError("MALFORMED_REQUEST", detail);
7096
7311
  }
7097
7312
  if (deps.auth?.spendAccountPay) {
@@ -7624,6 +7839,14 @@ var TOOLS = [
7624
7839
  type: "object",
7625
7840
  description: "JSON request body for a POST. Sent as application/json and bound to the payment."
7626
7841
  },
7842
+ file: {
7843
+ type: "string",
7844
+ description: "Absolute path under SUIPAY_MCP_FILE_ROOT (unset disables attach). Stdio POST only; requires fileField. Regular non-empty file whose decoded size fits the paid-body ceiling. Not a URL, FIFO, device, or path under ~/.suipay. Bytes fill json[fileField] as canonical base64."
7845
+ },
7846
+ fileField: {
7847
+ type: "string",
7848
+ description: "JSON key to set from file (e.g. contentBase64). Required with file. Pattern [A-Za-z][A-Za-z0-9_]{0,63}. Must not already be present on json."
7849
+ },
7627
7850
  recipient: {
7628
7851
  type: "string",
7629
7852
  description: "Sui address you expect to be paid. The payment is refused, unsigned, if the prepared transaction pays anyone else."
@@ -7731,6 +7954,7 @@ function toolError(value) {
7731
7954
  }
7732
7955
  function createServer2(cfg, auth, trace, options = {}) {
7733
7956
  const resolveAgentHeld = options.resolveAgentHeld ?? resolveAgentHeldSettlement;
7957
+ const transport = options.transport ?? "stdio";
7734
7958
  const server = new Server(
7735
7959
  { name: "suipay", version: "1.0.0" },
7736
7960
  {
@@ -7757,17 +7981,29 @@ function createServer2(cfg, auth, trace, options = {}) {
7757
7981
  return await accessContext({ auth }, cfg);
7758
7982
  case "pay": {
7759
7983
  const agentHeld = auth?.spendAccountPay ? resolveAgentHeld(cfg, auth.spendAccountPay) : null;
7984
+ const fileArgs = {
7985
+ ...args.file !== void 0 ? { file: args.file } : {},
7986
+ ...args.fileField !== void 0 ? { fileField: args.fileField } : {}
7987
+ };
7988
+ if (transport === "http" && hasLocalFileArgs(fileArgs)) {
7989
+ return closedPayError(
7990
+ "FILE_STDIO_ONLY",
7991
+ "file is stdio only; hosted /mcp does not read the buyer disk"
7992
+ );
7993
+ }
7760
7994
  return await pay(
7761
7995
  {
7762
7996
  url: String(args.url ?? ""),
7763
7997
  ...args.method !== void 0 ? { method: args.method } : {},
7764
7998
  ...args.json !== void 0 ? { json: args.json } : {},
7999
+ ...transport === "stdio" ? fileArgs : {},
7765
8000
  ...args.recipient !== void 0 ? { recipient: args.recipient } : {},
7766
8001
  ...args.maxAmount !== void 0 ? { maxAmount: args.maxAmount } : {}
7767
8002
  },
7768
8003
  cfg,
7769
8004
  {
7770
8005
  auth,
8006
+ transport,
7771
8007
  ...trace ? { trace } : {},
7772
8008
  ...agentHeld ? { agentHeld } : {}
7773
8009
  }
@@ -7856,6 +8092,11 @@ function canonicalMcpRequestId(id) {
7856
8092
  function asRecord(value) {
7857
8093
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
7858
8094
  }
8095
+ function redactPayFileArg(args) {
8096
+ const record = asRecord(args);
8097
+ if (!record || !("file" in record)) return args;
8098
+ return { ...record, file: "[redacted]" };
8099
+ }
7859
8100
  function readEntry(message) {
7860
8101
  const record = asRecord(message);
7861
8102
  if (!record) return null;
@@ -7867,7 +8108,7 @@ function readEntry(message) {
7867
8108
  jsonRpcId: typeof rawId === "string" || typeof rawId === "number" ? rawId : null,
7868
8109
  requestId: canonicalMcpRequestId(rawId),
7869
8110
  toolName: params && typeof params.name === "string" ? params.name : null,
7870
- toolArguments: params ? params.arguments : void 0,
8111
+ toolArguments: params ? redactPayFileArg(params.arguments) : void 0,
7871
8112
  clientName: clientInfo && typeof clientInfo.name === "string" ? clientInfo.name : null,
7872
8113
  clientVersion: clientInfo && typeof clientInfo.version === "string" ? clientInfo.version : null,
7873
8114
  protocolVersion: params && typeof params.protocolVersion === "string" ? params.protocolVersion : null
@@ -8297,7 +8538,10 @@ async function handleSuipayMcpHttpRequest(req, cfg, auth, trace, options) {
8297
8538
  sessionIdGenerator: void 0,
8298
8539
  enableJsonResponse: true
8299
8540
  });
8300
- const server = createServer2(cfg, auth, hooks, options);
8541
+ const server = createServer2(cfg, auth, hooks, {
8542
+ ...options,
8543
+ transport: "http"
8544
+ });
8301
8545
  await server.connect(transport);
8302
8546
  return transport.handleRequest(request);
8303
8547
  }
@@ -282,6 +282,14 @@ declare const TOOLS: readonly [{
282
282
  readonly type: "object";
283
283
  readonly description: "JSON request body for a POST. Sent as application/json and bound to the payment.";
284
284
  };
285
+ readonly file: {
286
+ readonly type: "string";
287
+ readonly description: "Absolute path under SUIPAY_MCP_FILE_ROOT (unset disables attach). Stdio POST only; requires fileField. Regular non-empty file whose decoded size fits the paid-body ceiling. Not a URL, FIFO, device, or path under ~/.suipay. Bytes fill json[fileField] as canonical base64.";
288
+ };
289
+ readonly fileField: {
290
+ readonly type: "string";
291
+ readonly description: "JSON key to set from file (e.g. contentBase64). Required with file. Pattern [A-Za-z][A-Za-z0-9_]{0,63}. Must not already be present on json.";
292
+ };
285
293
  readonly recipient: {
286
294
  readonly type: "string";
287
295
  readonly description: "Sui address you expect to be paid. The payment is refused, unsigned, if the prepared transaction pays anyone else.";
@@ -370,6 +378,11 @@ interface McpServerOptions {
370
378
  * does not already authorize.
371
379
  */
372
380
  resolveAgentHeld?: AgentHeldResolver;
381
+ /**
382
+ * Wire that created this server. Hosted HTTP never forwards `file` into `pay`.
383
+ * Stdio is the default so existing tests stay local.
384
+ */
385
+ transport?: 'stdio' | 'http';
373
386
  }
374
387
  declare function createServer(cfg: McpConfig, auth?: McpAuthContext, trace?: McpTraceHooks, options?: McpServerOptions): Server;
375
388
 
package/dist/http.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { m as handleSuipayMcpHttpRequest } from './http-B4YTVw0k.js';
1
+ export { m as handleSuipayMcpHttpRequest } from './http-DBP9qgVw.js';
2
2
  import '@cmdoss/suipay-core/policy/grant-target';
3
3
  import '@cmdoss/suipay-sdk/mcp/access-context';
4
4
  import '@cmdoss/suipay-sdk/buyer/settlement-dto';
package/dist/http.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleSuipayMcpHttpRequest
3
- } from "./chunk-THLDEMGS.js";
3
+ } from "./chunk-UTKVBAEZ.js";
4
4
  export {
5
5
  handleSuipayMcpHttpRequest
6
6
  };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Wallet } from '@cmdoss/suipay-core/chain/types';
2
- import { M as McpConfig, a as McpAuthContext, b as McpTraceHooks } from './http-B4YTVw0k.js';
3
- export { A as AgentHeldResolver, c as AgentHeldSettlement, d as MCP_TARGET_PRESETS, e as McpEnvelope, f as McpEnvelopeEntry, g as McpServerOptions, h as McpTarget, i as McpTraceContext, j as McpTraceRuntime, P as PACKAGE_NAME, T as TOOLS, k as canonicalMcpRequestId, l as createServer, m as handleSuipayMcpHttpRequest, n as inspectMcpEnvelope, o as loadMcpConfig, p as parseMcpTargetFlag, r as resetAgentHeldProcessLedger, q as resolveAgentHeldSettlement, s as resolveMcpTarget, t as sameMcpGateway, u as traceMcpHttpRequest } from './http-B4YTVw0k.js';
2
+ import { M as McpConfig, a as McpAuthContext, b as McpTraceHooks } from './http-DBP9qgVw.js';
3
+ export { A as AgentHeldResolver, c as AgentHeldSettlement, d as MCP_TARGET_PRESETS, e as McpEnvelope, f as McpEnvelopeEntry, g as McpServerOptions, h as McpTarget, i as McpTraceContext, j as McpTraceRuntime, P as PACKAGE_NAME, T as TOOLS, k as canonicalMcpRequestId, l as createServer, m as handleSuipayMcpHttpRequest, n as inspectMcpEnvelope, o as loadMcpConfig, p as parseMcpTargetFlag, r as resetAgentHeldProcessLedger, q as resolveAgentHeldSettlement, s as resolveMcpTarget, t as sameMcpGateway, u as traceMcpHttpRequest } from './http-DBP9qgVw.js';
4
4
  import { GrantSnapshot } from '@cmdoss/suipay-core/policy/grant-target';
5
5
  export { resolveGrantTarget } from '@cmdoss/suipay-core/policy/grant-target';
6
6
  import { PaidHttpRequest } from '@cmdoss/suipay-sdk/protocol/paid-http-request';
@@ -347,6 +347,8 @@ interface ToolDeps {
347
347
  profileLoader?: () => PaymentProfile | null;
348
348
  /** Remote HTTP auth (grant + scope + optional shared-pool pay session). */
349
349
  auth?: McpAuthContext;
350
+ /** Wire transport. Hosted HTTP never reads a buyer path. */
351
+ transport?: 'stdio' | 'http';
350
352
  /**
351
353
  * Proxy-resolved live trace for this MCP request. Observation only: it never
352
354
  * changes which rail runs, what is paid, or whether a payment is allowed.
@@ -377,6 +379,8 @@ declare function pay(args: {
377
379
  url: string;
378
380
  method?: unknown;
379
381
  json?: unknown;
382
+ file?: unknown;
383
+ fileField?: unknown;
380
384
  recipient?: unknown;
381
385
  maxAmount?: unknown;
382
386
  }, cfg: McpConfig, deps?: ToolDeps): Promise<ToolResult>;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadBootProfile,
3
3
  main
4
- } from "./chunk-P54ZYBPN.js";
4
+ } from "./chunk-AEV6Q6JC.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-THLDEMGS.js";
29
+ } from "./chunk-UTKVBAEZ.js";
30
30
  export {
31
31
  MCP_TARGET_PRESETS,
32
32
  PACKAGE_NAME,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cmdoss/suipay-mcp",
3
- "version": "0.2.2-dev.5",
3
+ "version": "0.2.2-dev.6",
4
4
  "type": "module",
5
- "description": "SuiPay MCP — pay MPP-gated APIs from a spend-account grant with an agent-held delegate key.",
5
+ "description": "SuiPay MCP \u2014 pay MPP-gated APIs from a spend-account grant with an agent-held delegate key.",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {