@cmdoss/suipay-mcp 0.2.2-dev.3 → 0.2.2-dev.30
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 +77 -14
- package/dist/bin/suipay.js +2 -2
- package/dist/{chunk-C2IYSV43.js → chunk-IH6HQD2V.js} +2 -2
- package/dist/{chunk-SRMAH6MK.js → chunk-YMOMYFKL.js} +5836 -810
- package/dist/{http-B4YTVw0k.d.ts → http-DvnvTrb3.d.ts} +268 -4
- package/dist/http.d.ts +5 -1
- package/dist/http.js +1 -1
- package/dist/index.d.ts +15 -210
- package/dist/index.js +2 -2
- package/package.json +15 -14
|
@@ -3,8 +3,12 @@ import { McpAccessContext } from '@cmdoss/suipay-sdk/mcp/access-context';
|
|
|
3
3
|
import { SettlementDTO } from '@cmdoss/suipay-sdk/buyer/settlement-dto';
|
|
4
4
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
5
5
|
import { GetObjectJson } from '@cmdoss/suipay-sdk/agent-sdk/reads';
|
|
6
|
-
import { DelegatedKeySigner, DelegatedPayerDeps } from '@cmdoss/suipay-sdk/delegated-signer/payer';
|
|
6
|
+
import { DelegatedKeySigner, DelegatedPayerDeps, GuardedSettleFields } from '@cmdoss/suipay-sdk/delegated-signer/payer';
|
|
7
7
|
import { TraceRunResolver, TraceSink } from '@cmdoss/suipay-core/trace/types';
|
|
8
|
+
import { PaidHttpRequest } from '@cmdoss/suipay-sdk/protocol/paid-http-request';
|
|
9
|
+
import { Dialect } from '@cmdoss/suipay-sdk/protocol/types';
|
|
10
|
+
import { PayOperationDeps } from '@cmdoss/suipay-sdk/pay-operation';
|
|
11
|
+
import { PaymentState, NextAction } from '@cmdoss/suipay-core/errors';
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Authenticated MCP request context (remote Streamable HTTP).
|
|
@@ -16,7 +20,7 @@ import { TraceRunResolver, TraceSink } from '@cmdoss/suipay-core/trace/types';
|
|
|
16
20
|
*
|
|
17
21
|
* Non-custodial: the gateway holds NO key that can spend. There is deliberately
|
|
18
22
|
* no `decryptDelegateSeed` and no forwarded `sponsorAuthorization` here — the
|
|
19
|
-
* `pay` tool only PREPARES an unsigned `spend_account::
|
|
23
|
+
* `pay` tool only PREPARES an unsigned `spend_account::settle_policy` / `settle_any_recipient` transaction from the
|
|
20
24
|
* immutable grant snapshot (`prepareSpendAccountPayment`), and the client that
|
|
21
25
|
* holds the delegate key signs locally and submits. Only signatures ever reach
|
|
22
26
|
* the gateway. See docs/design/mcp-non-custodial-signing.md and ADR-0013 §3.
|
|
@@ -40,7 +44,7 @@ interface McpAuthContext {
|
|
|
40
44
|
/** Public, descriptive policy context. Never used as payment authority. */
|
|
41
45
|
access?: McpAccessContext;
|
|
42
46
|
/**
|
|
43
|
-
* When present, `pay` prepares unsigned spend_account::
|
|
47
|
+
* When present, `pay` prepares unsigned spend_account::settle_policy / settle_any_recipient bytes for the
|
|
44
48
|
* client-held delegate key to sign locally — no server-side decrypt or
|
|
45
49
|
* signing. Stdio local V1 profile path remains when absent.
|
|
46
50
|
*/
|
|
@@ -79,6 +83,13 @@ interface McpConfig {
|
|
|
79
83
|
minFunded: bigint;
|
|
80
84
|
minMaxPerPayment: bigint;
|
|
81
85
|
label: string;
|
|
86
|
+
/**
|
|
87
|
+
* Optional override of the gateway's published `ExclusionDirectory` id.
|
|
88
|
+
* When null, pay reads `GET /v1/delegate/deployment` and turns the resolver
|
|
89
|
+
* on only if that response names one. The id here does not choose the
|
|
90
|
+
* directory a settle uses — the offer's `registryIdentity` does.
|
|
91
|
+
*/
|
|
92
|
+
exclusionDirectoryObjectId: string | null;
|
|
82
93
|
}
|
|
83
94
|
/**
|
|
84
95
|
* CLI flags: `--local` / `-local`, `--dev` / `-dev`. Unknown args are ignored
|
|
@@ -249,6 +260,244 @@ interface TraceMcpHttpRequestInput {
|
|
|
249
260
|
*/
|
|
250
261
|
declare function traceMcpHttpRequest(input: TraceMcpHttpRequestInput): Promise<Response>;
|
|
251
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Shared pay-request helpers.
|
|
265
|
+
*
|
|
266
|
+
* The V1 allowance sponsored payer (ADR-0010) is retired; only the
|
|
267
|
+
* rail-neutral request surface the SpendAccount payer depends on survives here:
|
|
268
|
+
* the `PayResult` shape every payer returns. `paidRequestInit` is the SDK helper
|
|
269
|
+
* that builds the one RequestInit replayed byte for byte on both calls.
|
|
270
|
+
*/
|
|
271
|
+
|
|
272
|
+
type PayResult = {
|
|
273
|
+
status: 'ok' | 'failed' | 'ambiguous';
|
|
274
|
+
/**
|
|
275
|
+
* `true` — settlement confirmed. `false` — money did not leave the
|
|
276
|
+
* account. `'unknown'` — execute/finality did not resolve; a retry can
|
|
277
|
+
* pay twice.
|
|
278
|
+
*/
|
|
279
|
+
paid: boolean | 'unknown';
|
|
280
|
+
/** Whether money moved; always agrees with `paid`. */
|
|
281
|
+
paymentState?: PaymentState;
|
|
282
|
+
body?: unknown;
|
|
283
|
+
receipt?: unknown;
|
|
284
|
+
/** Registry code on a failed or ambiguous result. */
|
|
285
|
+
code?: string;
|
|
286
|
+
retryable?: boolean;
|
|
287
|
+
nextAction?: NextAction;
|
|
288
|
+
supportCode?: string;
|
|
289
|
+
detail?: string;
|
|
290
|
+
txDigest?: string;
|
|
291
|
+
paymentId?: string;
|
|
292
|
+
challengeId?: string;
|
|
293
|
+
httpStatus?: number;
|
|
294
|
+
responseClass?: 'unpaid_ok' | 'rejected' | 'unavailable';
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* SpendAccount PREPARE-only client (non-custodial MCP).
|
|
299
|
+
*
|
|
300
|
+
* The remote MCP `pay` tool runs inside the gateway, which holds NO key that can
|
|
301
|
+
* spend. So this module does not sign or submit: it PREPARES a payment and hands
|
|
302
|
+
* back an unsigned `spend_account::settle_policy` / `settle_any_recipient` transaction plus everything the client
|
|
303
|
+
* needs. The client — which holds the delegate key — sponsors, signs locally,
|
|
304
|
+
* and submits through the same personal-message challenge → local-sign → submit flow the
|
|
305
|
+
* REST/SDK delegate path uses. Only signatures ever reach the gateway; the
|
|
306
|
+
* private key is never placed in an HTTP body, a bearer, or any header.
|
|
307
|
+
*
|
|
308
|
+
* Flow: 402 Offer → request-binding → package/network SSOT →
|
|
309
|
+
* resolveGrantTarget(snapshot, offer.targetHash) (pause/revoke gate) → cap/coin
|
|
310
|
+
* checks → assertLive (fresh authority) → build unsigned kind bytes → return the
|
|
311
|
+
* signing request. There is deliberately no sponsor call, no decrypt, no
|
|
312
|
+
* signature, and no forwarded bearer here.
|
|
313
|
+
*
|
|
314
|
+
* See docs/design/mcp-non-custodial-signing.md and ADR-0013 §3.
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
type SharedObjectReader = (objectId: string) => Promise<{
|
|
318
|
+
owner?: unknown;
|
|
319
|
+
} | null | undefined>;
|
|
320
|
+
/**
|
|
321
|
+
* Read/prepare-only session for the non-custodial MCP pay tool. It carries the
|
|
322
|
+
* immutable grant snapshot and an optional prepare-time live gate — and no key,
|
|
323
|
+
* by construction. There is no `decryptDelegateSeed` and no `sponsorAuthorization`.
|
|
324
|
+
*/
|
|
325
|
+
interface SpendAccountPrepareSession {
|
|
326
|
+
snapshot: GrantSnapshot;
|
|
327
|
+
/** SpendAccount package id (V2). */
|
|
328
|
+
packageId: string;
|
|
329
|
+
/**
|
|
330
|
+
* Re-assert the grant is still live (not paused/revoked/expired) against fresh
|
|
331
|
+
* canonical state, invoked immediately before a signing request is handed back.
|
|
332
|
+
* Throw to abort. Optional; when absent, only the request-time snapshot gates
|
|
333
|
+
* the prepare (on-chain `spend_account::settle_policy` remains the final backstop for any
|
|
334
|
+
* spend the client later submits).
|
|
335
|
+
*/
|
|
336
|
+
assertLive?: () => Promise<void>;
|
|
337
|
+
}
|
|
338
|
+
interface SpendAccountPayDeps {
|
|
339
|
+
fetchImpl?: typeof fetch;
|
|
340
|
+
/**
|
|
341
|
+
* Build only-transaction-kind bytes for the canonical guarded debit
|
|
342
|
+
* (`spend_account::settle_policy` / `settle_any_recipient`).
|
|
343
|
+
*
|
|
344
|
+
* The guarded-settle fields ({@link GuardedSettleFields}) are required on the
|
|
345
|
+
* fresh lineage: every delegate settle consumes the shared exclusion marker.
|
|
346
|
+
* Dropping them fails closed rather than building an unguarded call that no
|
|
347
|
+
* longer exists on chain.
|
|
348
|
+
*/
|
|
349
|
+
buildPayKind?: (input: {
|
|
350
|
+
delegate: string;
|
|
351
|
+
coinType: string;
|
|
352
|
+
poolObjectId: string;
|
|
353
|
+
grantObjectId: string;
|
|
354
|
+
policyId: number | string;
|
|
355
|
+
targetHash: string;
|
|
356
|
+
amount: string;
|
|
357
|
+
paymentIdHash: Uint8Array;
|
|
358
|
+
termsHash: Uint8Array;
|
|
359
|
+
recipient?: string;
|
|
360
|
+
accessMode?: 'scoped' | 'open';
|
|
361
|
+
} & GuardedSettleFields) => Promise<{
|
|
362
|
+
kindBytes: string;
|
|
363
|
+
}>;
|
|
364
|
+
/**
|
|
365
|
+
* Resolve the per-recipient `RecipientRegistry` bound in the offer's exclusion
|
|
366
|
+
* directory (guarded offers only). Injected seam for tests; production
|
|
367
|
+
* leaves it unset and the prepare wires a live gRPC-backed resolver from the
|
|
368
|
+
* configured `ExclusionDirectory` id when present, else fails closed.
|
|
369
|
+
*/
|
|
370
|
+
resolveExclusionRegistry?: PayOperationDeps['resolveExclusionRegistry'];
|
|
371
|
+
/**
|
|
372
|
+
* Read a shared object's owner so prepare binds the real initial version.
|
|
373
|
+
* Missing owner fails the prepare; version 1 is not a substitute.
|
|
374
|
+
*/
|
|
375
|
+
readSharedObject?: SharedObjectReader;
|
|
376
|
+
/**
|
|
377
|
+
* Live trace for this prepare. Purely observational: emission records what the
|
|
378
|
+
* canonical read decisions already returned — an event is written after a check
|
|
379
|
+
* passes and can never be the thing that lets the next step run.
|
|
380
|
+
*/
|
|
381
|
+
trace?: SpendAccountPayTrace;
|
|
382
|
+
}
|
|
383
|
+
interface SpendAccountPayTrace {
|
|
384
|
+
sink: TraceSink;
|
|
385
|
+
traceId: string;
|
|
386
|
+
requestId: string | null;
|
|
387
|
+
buyerAccountId: string;
|
|
388
|
+
connectionId: string;
|
|
389
|
+
/** HMAC secret for signed cross-request context. Absent disables signing. */
|
|
390
|
+
secret?: string | null;
|
|
391
|
+
/** Injected clock, for tests. */
|
|
392
|
+
now?: () => number;
|
|
393
|
+
}
|
|
394
|
+
/** The unsigned payment the client signs locally and submits. */
|
|
395
|
+
interface SpendAccountSigningRequest {
|
|
396
|
+
/**
|
|
397
|
+
* Unsigned `spend_account::settle_policy` / `settle_any_recipient` transaction-kind bytes (base64), sender set to
|
|
398
|
+
* `delegateAddress`. The client sponsors these for gas, signs with the delegate
|
|
399
|
+
* key, and submits — the gateway never receives the key.
|
|
400
|
+
*/
|
|
401
|
+
unsignedKindBytes: string;
|
|
402
|
+
delegateAddress: string;
|
|
403
|
+
packageId: string;
|
|
404
|
+
poolObjectId: string;
|
|
405
|
+
grantObjectId: string;
|
|
406
|
+
/** On-chain policy id the pay is bound to. */
|
|
407
|
+
policyId: number | string;
|
|
408
|
+
coinType: string;
|
|
409
|
+
targetHash: string;
|
|
410
|
+
amount: string;
|
|
411
|
+
/** Hex (no 0x) of the payment-id hash bound into the transaction. */
|
|
412
|
+
paymentIdHashHex: string;
|
|
413
|
+
/** Hex (no 0x) of the terms hash bound into the transaction. */
|
|
414
|
+
termsHashHex: string;
|
|
415
|
+
challengeId: string;
|
|
416
|
+
/** The exact paid request to replay after the client submits. */
|
|
417
|
+
resource: {
|
|
418
|
+
url: string;
|
|
419
|
+
method: string;
|
|
420
|
+
};
|
|
421
|
+
dialect: Dialect;
|
|
422
|
+
/** Recipient the agent requested (offer.payTo). */
|
|
423
|
+
recipient: string;
|
|
424
|
+
/** Where the client (holding the key) sponsors and submits. */
|
|
425
|
+
submit: {
|
|
426
|
+
sponsorUrl: string;
|
|
427
|
+
executeUrl: string;
|
|
428
|
+
moveCallTarget: string;
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
431
|
+
* ISO-8601 timestamp when this prepared operation expires. After this time the
|
|
432
|
+
* unsigned bytes are no longer valid and the client must re-call pay() for a
|
|
433
|
+
* fresh prepare. Derived from the offer TTL.
|
|
434
|
+
*/
|
|
435
|
+
expiresAt: string;
|
|
436
|
+
/** Restated hard rule for the agent host. */
|
|
437
|
+
note: string;
|
|
438
|
+
}
|
|
439
|
+
interface PreparedPayment {
|
|
440
|
+
status: 'prepared';
|
|
441
|
+
paid: false;
|
|
442
|
+
signingRequest: SpendAccountSigningRequest;
|
|
443
|
+
}
|
|
444
|
+
/** Prepared signing request, or a canonical failure (never a spend). */
|
|
445
|
+
type SpendAccountPrepareResult = PreparedPayment | PayResult;
|
|
446
|
+
/** Default kind builder (no chain client — pure PTB). */
|
|
447
|
+
declare function buildSpendAccountPayKind(input: {
|
|
448
|
+
packageId: string;
|
|
449
|
+
delegate: string;
|
|
450
|
+
coinType: string;
|
|
451
|
+
poolObjectId: string;
|
|
452
|
+
grantObjectId: string;
|
|
453
|
+
policyId: number | string;
|
|
454
|
+
targetHash: string;
|
|
455
|
+
amount: string;
|
|
456
|
+
paymentIdHash: Uint8Array;
|
|
457
|
+
termsHash: Uint8Array;
|
|
458
|
+
poolInitialSharedVersion?: string;
|
|
459
|
+
grantInitialSharedVersion?: string;
|
|
460
|
+
clockInitialSharedVersion?: string;
|
|
461
|
+
} & GuardedSettleFields): Promise<{
|
|
462
|
+
kindBytes: string;
|
|
463
|
+
}>;
|
|
464
|
+
/**
|
|
465
|
+
* Refuse blind signing: a client validating a sponsored transaction must be able
|
|
466
|
+
* to prove the sponsored bytes reconstruct the intended spend_account::settle_policy. Kept
|
|
467
|
+
* here (and exported) so both the client signer and its tests share one check.
|
|
468
|
+
*/
|
|
469
|
+
declare function verifySpendAccountPayReconstructs(bytes: string, expected: {
|
|
470
|
+
kindBytes: string;
|
|
471
|
+
packageId: string;
|
|
472
|
+
delegate: string;
|
|
473
|
+
poolObjectId: string;
|
|
474
|
+
grantObjectId: string;
|
|
475
|
+
amount: string;
|
|
476
|
+
}): void;
|
|
477
|
+
/**
|
|
478
|
+
* Prepare a delegate payment WITHOUT signing. Reads the 402 offer, binds it,
|
|
479
|
+
* gates on the immutable grant snapshot + a fresh authority check, builds the
|
|
480
|
+
* unsigned transaction, and returns a signing request. The client holding the
|
|
481
|
+
* delegate key signs locally and submits. This function never decrypts, signs,
|
|
482
|
+
* sponsors, or submits.
|
|
483
|
+
*
|
|
484
|
+
* Uses `resolvePayment` from the SDK pay-operation module for the
|
|
485
|
+
* shared offer-acquisition + authority-resolution pipeline (steps 1–5 + assertLive
|
|
486
|
+
* + hash derivation + buildPayKind). This module wraps that with MCP-specific
|
|
487
|
+
* concerns: trace events, dialect-mode ceiling check, and signing-request
|
|
488
|
+
* construction.
|
|
489
|
+
*/
|
|
490
|
+
declare function prepareSpendAccountPayment(args: {
|
|
491
|
+
url: string;
|
|
492
|
+
/** The one normalized paid request, replayed byte for byte after signing. */
|
|
493
|
+
request?: PaidHttpRequest;
|
|
494
|
+
session: SpendAccountPrepareSession;
|
|
495
|
+
cfg: McpConfig;
|
|
496
|
+
deps?: SpendAccountPayDeps;
|
|
497
|
+
/** Preferred dialect when the 402 advertises both (default mpp). */
|
|
498
|
+
preferredDialect?: Dialect;
|
|
499
|
+
}): Promise<SpendAccountPrepareResult>;
|
|
500
|
+
|
|
252
501
|
/**
|
|
253
502
|
* Transport-neutral SuiPay MCP server + tool registry.
|
|
254
503
|
* Used by stdio (index.ts) and Streamable HTTP (http.ts).
|
|
@@ -282,6 +531,14 @@ declare const TOOLS: readonly [{
|
|
|
282
531
|
readonly type: "object";
|
|
283
532
|
readonly description: "JSON request body for a POST. Sent as application/json and bound to the payment.";
|
|
284
533
|
};
|
|
534
|
+
readonly file: {
|
|
535
|
+
readonly type: "string";
|
|
536
|
+
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.";
|
|
537
|
+
};
|
|
538
|
+
readonly fileField: {
|
|
539
|
+
readonly type: "string";
|
|
540
|
+
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.";
|
|
541
|
+
};
|
|
285
542
|
readonly recipient: {
|
|
286
543
|
readonly type: "string";
|
|
287
544
|
readonly description: "Sui address you expect to be paid. The payment is refused, unsigned, if the prepared transaction pays anyone else.";
|
|
@@ -370,6 +627,13 @@ interface McpServerOptions {
|
|
|
370
627
|
* does not already authorize.
|
|
371
628
|
*/
|
|
372
629
|
resolveAgentHeld?: AgentHeldResolver;
|
|
630
|
+
/** Override the exclusion-registry resolver (tests / offline). */
|
|
631
|
+
resolveExclusionRegistry?: SpendAccountPayDeps['resolveExclusionRegistry'];
|
|
632
|
+
/**
|
|
633
|
+
* Wire that created this server. Hosted HTTP never forwards `file` into `pay`.
|
|
634
|
+
* Stdio is the default so existing tests stay local.
|
|
635
|
+
*/
|
|
636
|
+
transport?: 'stdio' | 'http';
|
|
373
637
|
}
|
|
374
638
|
declare function createServer(cfg: McpConfig, auth?: McpAuthContext, trace?: McpTraceHooks, options?: McpServerOptions): Server;
|
|
375
639
|
|
|
@@ -389,4 +653,4 @@ declare function createServer(cfg: McpConfig, auth?: McpAuthContext, trace?: Mcp
|
|
|
389
653
|
*/
|
|
390
654
|
declare function handleSuipayMcpHttpRequest(req: Request, cfg: McpConfig, auth?: McpAuthContext, trace?: McpTraceRuntime | null, options?: McpServerOptions): Promise<Response>;
|
|
391
655
|
|
|
392
|
-
export { type AgentHeldResolver as A, type McpConfig as M, PACKAGE_NAME as P, TOOLS as T, type McpAuthContext as a, type McpTraceHooks as b, type
|
|
656
|
+
export { type AgentHeldResolver as A, traceMcpHttpRequest as B, verifySpendAccountPayReconstructs as C, type McpConfig as M, PACKAGE_NAME as P, type SpendAccountSigningRequest as S, TOOLS as T, type McpAuthContext as a, type McpTraceHooks as b, type SpendAccountPayDeps as c, type AgentHeldSettlement as d, MCP_TARGET_PRESETS as e, type McpEnvelope as f, type McpEnvelopeEntry as g, type McpServerOptions as h, type McpTarget as i, type McpTraceContext as j, type McpTraceRuntime as k, type PreparedPayment as l, type SpendAccountPrepareResult as m, type SpendAccountPrepareSession as n, buildSpendAccountPayKind as o, canonicalMcpRequestId as p, createServer as q, handleSuipayMcpHttpRequest as r, inspectMcpEnvelope as s, loadMcpConfig as t, parseMcpTargetFlag as u, prepareSpendAccountPayment as v, resetAgentHeldProcessLedger as w, resolveAgentHeldSettlement as x, resolveMcpTarget as y, sameMcpGateway as z };
|
package/dist/http.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { r as handleSuipayMcpHttpRequest } from './http-DvnvTrb3.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';
|
|
@@ -6,3 +6,7 @@ import '@modelcontextprotocol/sdk/server/index.js';
|
|
|
6
6
|
import '@cmdoss/suipay-sdk/agent-sdk/reads';
|
|
7
7
|
import '@cmdoss/suipay-sdk/delegated-signer/payer';
|
|
8
8
|
import '@cmdoss/suipay-core/trace/types';
|
|
9
|
+
import '@cmdoss/suipay-sdk/protocol/paid-http-request';
|
|
10
|
+
import '@cmdoss/suipay-sdk/protocol/types';
|
|
11
|
+
import '@cmdoss/suipay-sdk/pay-operation';
|
|
12
|
+
import '@cmdoss/suipay-core/errors';
|
package/dist/http.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { Wallet } from '@cmdoss/suipay-core/chain/types';
|
|
2
|
-
import { M as McpConfig, a as McpAuthContext, b as McpTraceHooks } from './http-
|
|
3
|
-
export { A as AgentHeldResolver,
|
|
4
|
-
import { GrantSnapshot } from '@cmdoss/suipay-core/policy/grant-target';
|
|
5
|
-
export { resolveGrantTarget } from '@cmdoss/suipay-core/policy/grant-target';
|
|
6
|
-
import { PaidHttpRequest } from '@cmdoss/suipay-sdk/protocol/paid-http-request';
|
|
7
|
-
import { TraceSink } from '@cmdoss/suipay-core/trace/types';
|
|
8
|
-
import { Dialect } from '@cmdoss/suipay-sdk/protocol/types';
|
|
2
|
+
import { S as SpendAccountSigningRequest, M as McpConfig, a as McpAuthContext, b as McpTraceHooks, c as SpendAccountPayDeps } from './http-DvnvTrb3.js';
|
|
3
|
+
export { A as AgentHeldResolver, d as AgentHeldSettlement, e as MCP_TARGET_PRESETS, f as McpEnvelope, g as McpEnvelopeEntry, h as McpServerOptions, i as McpTarget, j as McpTraceContext, k as McpTraceRuntime, P as PACKAGE_NAME, l as PreparedPayment, m as SpendAccountPrepareResult, n as SpendAccountPrepareSession, T as TOOLS, o as buildSpendAccountPayKind, p as canonicalMcpRequestId, q as createServer, r as handleSuipayMcpHttpRequest, s as inspectMcpEnvelope, t as loadMcpConfig, u as parseMcpTargetFlag, v as prepareSpendAccountPayment, w as resetAgentHeldProcessLedger, x as resolveAgentHeldSettlement, y as resolveMcpTarget, z as sameMcpGateway, B as traceMcpHttpRequest, C as verifySpendAccountPayReconstructs } from './http-DvnvTrb3.js';
|
|
9
4
|
import { GetObjectJson, createReader } from '@cmdoss/suipay-sdk/agent-sdk/reads';
|
|
10
5
|
import { DelegatedKeySigner, DelegatedPayerSession, DelegatedPayerConfig, DelegatedPayerDeps, SpendIntent, DelegatedPayResult } from '@cmdoss/suipay-sdk/delegated-signer/payer';
|
|
6
|
+
import { PaidHttpRequest } from '@cmdoss/suipay-sdk/protocol/paid-http-request';
|
|
11
7
|
import { createPayer } from '@cmdoss/suipay-sdk/agent-sdk/delegate-agent';
|
|
12
8
|
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
export { resolveGrantTarget } from '@cmdoss/suipay-core/policy/grant-target';
|
|
13
10
|
import '@cmdoss/suipay-sdk/mcp/access-context';
|
|
14
11
|
import '@cmdoss/suipay-sdk/buyer/settlement-dto';
|
|
15
12
|
import '@modelcontextprotocol/sdk/server/index.js';
|
|
13
|
+
import '@cmdoss/suipay-core/trace/types';
|
|
14
|
+
import '@cmdoss/suipay-sdk/protocol/types';
|
|
15
|
+
import '@cmdoss/suipay-sdk/pay-operation';
|
|
16
|
+
import '@cmdoss/suipay-core/errors';
|
|
16
17
|
|
|
17
18
|
interface SuiPayCredentials {
|
|
18
19
|
/** 64-hex Ed25519 seed. NEVER logged. */
|
|
@@ -68,208 +69,6 @@ declare function loadLocalSigner(): {
|
|
|
68
69
|
signPersonalMessage: (message: Uint8Array) => Promise<string>;
|
|
69
70
|
} | null;
|
|
70
71
|
|
|
71
|
-
/**
|
|
72
|
-
* Shared pay-request helpers.
|
|
73
|
-
*
|
|
74
|
-
* The V1 allowance sponsored payer (ADR-0010) is retired; only the
|
|
75
|
-
* rail-neutral request surface the SpendAccount payer depends on survives here:
|
|
76
|
-
* the `PayResult` shape every payer returns. `paidRequestInit` is the SDK helper
|
|
77
|
-
* that builds the one RequestInit replayed byte for byte on both calls.
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
type PayResult = {
|
|
81
|
-
status: 'ok' | 'failed' | 'ambiguous';
|
|
82
|
-
/**
|
|
83
|
-
* `true` — settlement confirmed. `false` — money did not leave the
|
|
84
|
-
* account. `'unknown'` — execute/finality did not resolve; a retry can
|
|
85
|
-
* pay twice.
|
|
86
|
-
*/
|
|
87
|
-
paid: boolean | 'unknown';
|
|
88
|
-
body?: unknown;
|
|
89
|
-
receipt?: unknown;
|
|
90
|
-
code?: string;
|
|
91
|
-
detail?: string;
|
|
92
|
-
txDigest?: string;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* SpendAccount PREPARE-only client (non-custodial MCP).
|
|
97
|
-
*
|
|
98
|
-
* The remote MCP `pay` tool runs inside the gateway, which holds NO key that can
|
|
99
|
-
* spend. So this module does not sign or submit: it PREPARES a payment and hands
|
|
100
|
-
* back an unsigned `spend_account::settle_policy_payment` transaction plus everything the client
|
|
101
|
-
* needs. The client — which holds the delegate key — sponsors, signs locally,
|
|
102
|
-
* and submits through the same personal-message challenge → local-sign → submit flow the
|
|
103
|
-
* REST/SDK delegate path uses. Only signatures ever reach the gateway; the
|
|
104
|
-
* private key is never placed in an HTTP body, a bearer, or any header.
|
|
105
|
-
*
|
|
106
|
-
* Flow: 402 Offer → request-binding → package/network SSOT →
|
|
107
|
-
* resolveGrantTarget(snapshot, offer.targetHash) (pause/revoke gate) → cap/coin
|
|
108
|
-
* checks → assertLive (fresh authority) → build unsigned kind bytes → return the
|
|
109
|
-
* signing request. There is deliberately no sponsor call, no decrypt, no
|
|
110
|
-
* signature, and no forwarded bearer here.
|
|
111
|
-
*
|
|
112
|
-
* See docs/design/mcp-non-custodial-signing.md and ADR-0013 §3.
|
|
113
|
-
*/
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Read/prepare-only session for the non-custodial MCP pay tool. It carries the
|
|
117
|
-
* immutable grant snapshot and an optional prepare-time live gate — and no key,
|
|
118
|
-
* by construction. There is no `decryptDelegateSeed` and no `sponsorAuthorization`.
|
|
119
|
-
*/
|
|
120
|
-
interface SpendAccountPrepareSession {
|
|
121
|
-
snapshot: GrantSnapshot;
|
|
122
|
-
/** SpendAccount package id (V2). */
|
|
123
|
-
packageId: string;
|
|
124
|
-
/**
|
|
125
|
-
* Re-assert the grant is still live (not paused/revoked/expired) against fresh
|
|
126
|
-
* canonical state, invoked immediately before a signing request is handed back.
|
|
127
|
-
* Throw to abort. Optional; when absent, only the request-time snapshot gates
|
|
128
|
-
* the prepare (on-chain `spend_account::settle_policy_payment` remains the final backstop for any
|
|
129
|
-
* spend the client later submits).
|
|
130
|
-
*/
|
|
131
|
-
assertLive?: () => Promise<void>;
|
|
132
|
-
}
|
|
133
|
-
interface SpendAccountPayDeps {
|
|
134
|
-
fetchImpl?: typeof fetch;
|
|
135
|
-
/** Build only-transaction-kind bytes for spend_account::settle_policy_payment. */
|
|
136
|
-
buildPayKind?: (input: {
|
|
137
|
-
delegate: string;
|
|
138
|
-
coinType: string;
|
|
139
|
-
poolObjectId: string;
|
|
140
|
-
grantObjectId: string;
|
|
141
|
-
policyId: number | string;
|
|
142
|
-
targetHash: string;
|
|
143
|
-
amount: string;
|
|
144
|
-
paymentIdHash: Uint8Array;
|
|
145
|
-
termsHash: Uint8Array;
|
|
146
|
-
recipient?: string;
|
|
147
|
-
accessMode?: 'scoped' | 'open';
|
|
148
|
-
}) => Promise<{
|
|
149
|
-
kindBytes: string;
|
|
150
|
-
}>;
|
|
151
|
-
/**
|
|
152
|
-
* Live trace for this prepare. Purely observational: emission records what the
|
|
153
|
-
* canonical read decisions already returned — an event is written after a check
|
|
154
|
-
* passes and can never be the thing that lets the next step run.
|
|
155
|
-
*/
|
|
156
|
-
trace?: SpendAccountPayTrace;
|
|
157
|
-
}
|
|
158
|
-
interface SpendAccountPayTrace {
|
|
159
|
-
sink: TraceSink;
|
|
160
|
-
traceId: string;
|
|
161
|
-
requestId: string | null;
|
|
162
|
-
buyerAccountId: string;
|
|
163
|
-
connectionId: string;
|
|
164
|
-
/** HMAC secret for signed cross-request context. Absent disables signing. */
|
|
165
|
-
secret?: string | null;
|
|
166
|
-
/** Injected clock, for tests. */
|
|
167
|
-
now?: () => number;
|
|
168
|
-
}
|
|
169
|
-
/** The unsigned payment the client signs locally and submits. */
|
|
170
|
-
interface SpendAccountSigningRequest {
|
|
171
|
-
/**
|
|
172
|
-
* Unsigned `spend_account::settle_policy_payment` transaction-kind bytes (base64), sender set to
|
|
173
|
-
* `delegateAddress`. The client sponsors these for gas, signs with the delegate
|
|
174
|
-
* key, and submits — the gateway never receives the key.
|
|
175
|
-
*/
|
|
176
|
-
unsignedKindBytes: string;
|
|
177
|
-
delegateAddress: string;
|
|
178
|
-
packageId: string;
|
|
179
|
-
poolObjectId: string;
|
|
180
|
-
grantObjectId: string;
|
|
181
|
-
/** On-chain policy id the pay is bound to. */
|
|
182
|
-
policyId: number | string;
|
|
183
|
-
coinType: string;
|
|
184
|
-
targetHash: string;
|
|
185
|
-
amount: string;
|
|
186
|
-
/** Hex (no 0x) of the payment-id hash bound into the transaction. */
|
|
187
|
-
paymentIdHashHex: string;
|
|
188
|
-
/** Hex (no 0x) of the terms hash bound into the transaction. */
|
|
189
|
-
termsHashHex: string;
|
|
190
|
-
challengeId: string;
|
|
191
|
-
/** The exact paid request to replay after the client submits. */
|
|
192
|
-
resource: {
|
|
193
|
-
url: string;
|
|
194
|
-
method: string;
|
|
195
|
-
};
|
|
196
|
-
dialect: Dialect;
|
|
197
|
-
/** Recipient the agent requested (offer.payTo). */
|
|
198
|
-
recipient: string;
|
|
199
|
-
/** Where the client (holding the key) sponsors and submits. */
|
|
200
|
-
submit: {
|
|
201
|
-
sponsorUrl: string;
|
|
202
|
-
executeUrl: string;
|
|
203
|
-
moveCallTarget: string;
|
|
204
|
-
};
|
|
205
|
-
/**
|
|
206
|
-
* ISO-8601 timestamp when this prepared operation expires. After this time the
|
|
207
|
-
* unsigned bytes are no longer valid and the client must re-call pay() for a
|
|
208
|
-
* fresh prepare. Derived from the offer TTL.
|
|
209
|
-
*/
|
|
210
|
-
expiresAt: string;
|
|
211
|
-
/** Restated hard rule for the agent host. */
|
|
212
|
-
note: string;
|
|
213
|
-
}
|
|
214
|
-
interface PreparedPayment {
|
|
215
|
-
status: 'prepared';
|
|
216
|
-
paid: false;
|
|
217
|
-
signingRequest: SpendAccountSigningRequest;
|
|
218
|
-
}
|
|
219
|
-
/** Prepared signing request, or a canonical failure (never a spend). */
|
|
220
|
-
type SpendAccountPrepareResult = PreparedPayment | PayResult;
|
|
221
|
-
/** Default kind builder (no chain client — pure PTB). */
|
|
222
|
-
declare function buildSpendAccountPayKind(input: {
|
|
223
|
-
packageId: string;
|
|
224
|
-
delegate: string;
|
|
225
|
-
coinType: string;
|
|
226
|
-
poolObjectId: string;
|
|
227
|
-
grantObjectId: string;
|
|
228
|
-
policyId: number | string;
|
|
229
|
-
targetHash: string;
|
|
230
|
-
amount: string;
|
|
231
|
-
paymentIdHash: Uint8Array;
|
|
232
|
-
termsHash: Uint8Array;
|
|
233
|
-
}): Promise<{
|
|
234
|
-
kindBytes: string;
|
|
235
|
-
}>;
|
|
236
|
-
/**
|
|
237
|
-
* Refuse blind signing: a client validating a sponsored transaction must be able
|
|
238
|
-
* to prove the sponsored bytes reconstruct the intended spend_account::settle_policy_payment. Kept
|
|
239
|
-
* here (and exported) so both the client signer and its tests share one check.
|
|
240
|
-
*/
|
|
241
|
-
declare function verifySpendAccountPayReconstructs(bytes: string, expected: {
|
|
242
|
-
kindBytes: string;
|
|
243
|
-
packageId: string;
|
|
244
|
-
delegate: string;
|
|
245
|
-
poolObjectId: string;
|
|
246
|
-
grantObjectId: string;
|
|
247
|
-
amount: string;
|
|
248
|
-
}): void;
|
|
249
|
-
/**
|
|
250
|
-
* Prepare a delegate payment WITHOUT signing. Reads the 402 offer, binds it,
|
|
251
|
-
* gates on the immutable grant snapshot + a fresh authority check, builds the
|
|
252
|
-
* unsigned transaction, and returns a signing request. The client holding the
|
|
253
|
-
* delegate key signs locally and submits. This function never decrypts, signs,
|
|
254
|
-
* sponsors, or submits.
|
|
255
|
-
*
|
|
256
|
-
* Uses `resolvePayment` from the SDK pay-operation module (SAIP-170) for the
|
|
257
|
-
* shared offer-acquisition + authority-resolution pipeline (steps 1–5 + assertLive
|
|
258
|
-
* + hash derivation + buildPayKind). This module wraps that with MCP-specific
|
|
259
|
-
* concerns: trace events, dialect-mode ceiling check, and signing-request
|
|
260
|
-
* construction.
|
|
261
|
-
*/
|
|
262
|
-
declare function prepareSpendAccountPayment(args: {
|
|
263
|
-
url: string;
|
|
264
|
-
/** The one normalized paid request, replayed byte for byte after signing. */
|
|
265
|
-
request?: PaidHttpRequest;
|
|
266
|
-
session: SpendAccountPrepareSession;
|
|
267
|
-
cfg: McpConfig;
|
|
268
|
-
deps?: SpendAccountPayDeps;
|
|
269
|
-
/** Preferred dialect when the 402 advertises both (default mpp). */
|
|
270
|
-
preferredDialect?: Dialect;
|
|
271
|
-
}): Promise<SpendAccountPrepareResult>;
|
|
272
|
-
|
|
273
72
|
/**
|
|
274
73
|
* Client-side completion of an MCP prepared payment.
|
|
275
74
|
*
|
|
@@ -347,6 +146,8 @@ interface ToolDeps {
|
|
|
347
146
|
profileLoader?: () => PaymentProfile | null;
|
|
348
147
|
/** Remote HTTP auth (grant + scope + optional shared-pool pay session). */
|
|
349
148
|
auth?: McpAuthContext;
|
|
149
|
+
/** Wire transport. Hosted HTTP never reads a buyer path. */
|
|
150
|
+
transport?: 'stdio' | 'http';
|
|
350
151
|
/**
|
|
351
152
|
* Proxy-resolved live trace for this MCP request. Observation only: it never
|
|
352
153
|
* changes which rail runs, what is paid, or whether a payment is allowed.
|
|
@@ -364,6 +165,8 @@ interface ToolDeps {
|
|
|
364
165
|
};
|
|
365
166
|
/** Override the prepare-time kind builder (tests / offline). */
|
|
366
167
|
buildPayKind?: SpendAccountPayDeps['buildPayKind'];
|
|
168
|
+
/** Override the exclusion-registry resolver (tests / offline). */
|
|
169
|
+
resolveExclusionRegistry?: SpendAccountPayDeps['resolveExclusionRegistry'];
|
|
367
170
|
/**
|
|
368
171
|
* Stdio login surfaces the console URL (MCP progress notification). The URL
|
|
369
172
|
* carries the delegate address only — never the seed.
|
|
@@ -377,6 +180,8 @@ declare function pay(args: {
|
|
|
377
180
|
url: string;
|
|
378
181
|
method?: unknown;
|
|
379
182
|
json?: unknown;
|
|
183
|
+
file?: unknown;
|
|
184
|
+
fileField?: unknown;
|
|
380
185
|
recipient?: unknown;
|
|
381
186
|
maxAmount?: unknown;
|
|
382
187
|
}, cfg: McpConfig, deps?: ToolDeps): Promise<ToolResult>;
|
|
@@ -390,4 +195,4 @@ declare function loadBootProfile(load?: typeof loadPaymentProfile): {
|
|
|
390
195
|
};
|
|
391
196
|
declare function main(): Promise<void>;
|
|
392
197
|
|
|
393
|
-
export { McpAuthContext, McpConfig, McpTraceHooks,
|
|
198
|
+
export { McpAuthContext, McpConfig, McpTraceHooks, SpendAccountSigningRequest, ensureLocalSigningKey, loadBootProfile, loadLocalSigner, main, pay, receipts, settlePreparedMcpPayment };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadBootProfile,
|
|
3
3
|
main
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IH6HQD2V.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-
|
|
29
|
+
} from "./chunk-YMOMYFKL.js";
|
|
30
30
|
export {
|
|
31
31
|
MCP_TARGET_PRESETS,
|
|
32
32
|
PACKAGE_NAME,
|