@forestrie/mcp-register 0.0.0-stage → 0.1.1

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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +178 -2
  3. package/bin/mcp-register.mjs +2 -0
  4. package/dist/core/base64.d.ts +7 -0
  5. package/dist/core/base64.d.ts.map +1 -0
  6. package/dist/core/base64.js +20 -0
  7. package/dist/core/base64.js.map +1 -0
  8. package/dist/core/delegation.d.ts +56 -0
  9. package/dist/core/delegation.d.ts.map +1 -0
  10. package/dist/core/delegation.js +130 -0
  11. package/dist/core/delegation.js.map +1 -0
  12. package/dist/core/grant.d.ts +41 -0
  13. package/dist/core/grant.d.ts.map +1 -0
  14. package/dist/core/grant.js +78 -0
  15. package/dist/core/grant.js.map +1 -0
  16. package/dist/core/hex.d.ts +4 -0
  17. package/dist/core/hex.d.ts.map +1 -0
  18. package/dist/core/hex.js +18 -0
  19. package/dist/core/hex.js.map +1 -0
  20. package/dist/core/index.d.ts +28 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/core/index.js +21 -0
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/issue.d.ts +38 -0
  25. package/dist/core/issue.d.ts.map +1 -0
  26. package/dist/core/issue.js +135 -0
  27. package/dist/core/issue.js.map +1 -0
  28. package/dist/core/limits.d.ts +9 -0
  29. package/dist/core/limits.d.ts.map +1 -0
  30. package/dist/core/limits.js +9 -0
  31. package/dist/core/limits.js.map +1 -0
  32. package/dist/core/scrapi.d.ts +66 -0
  33. package/dist/core/scrapi.d.ts.map +1 -0
  34. package/dist/core/scrapi.js +174 -0
  35. package/dist/core/scrapi.js.map +1 -0
  36. package/dist/core/signer.d.ts +24 -0
  37. package/dist/core/signer.d.ts.map +1 -0
  38. package/dist/core/signer.js +2 -0
  39. package/dist/core/signer.js.map +1 -0
  40. package/dist/core/statement.d.ts +26 -0
  41. package/dist/core/statement.d.ts.map +1 -0
  42. package/dist/core/statement.js +70 -0
  43. package/dist/core/statement.js.map +1 -0
  44. package/dist/core/version.d.ts +23 -0
  45. package/dist/core/version.d.ts.map +1 -0
  46. package/dist/core/version.js +23 -0
  47. package/dist/core/version.js.map +1 -0
  48. package/dist/core/x402.d.ts +99 -0
  49. package/dist/core/x402.d.ts.map +1 -0
  50. package/dist/core/x402.js +202 -0
  51. package/dist/core/x402.js.map +1 -0
  52. package/dist/net/delegate.d.ts +56 -0
  53. package/dist/net/delegate.d.ts.map +1 -0
  54. package/dist/net/delegate.js +182 -0
  55. package/dist/net/delegate.js.map +1 -0
  56. package/dist/net/http.d.ts +17 -0
  57. package/dist/net/http.d.ts.map +1 -0
  58. package/dist/net/http.js +52 -0
  59. package/dist/net/http.js.map +1 -0
  60. package/dist/net/index.d.ts +14 -0
  61. package/dist/net/index.d.ts.map +1 -0
  62. package/dist/net/index.js +13 -0
  63. package/dist/net/index.js.map +1 -0
  64. package/dist/net/write.d.ts +55 -0
  65. package/dist/net/write.d.ts.map +1 -0
  66. package/dist/net/write.js +46 -0
  67. package/dist/net/write.js.map +1 -0
  68. package/dist/node/cli.d.ts +8 -0
  69. package/dist/node/cli.d.ts.map +1 -0
  70. package/dist/node/cli.js +143 -0
  71. package/dist/node/cli.js.map +1 -0
  72. package/dist/node/grant-store.d.ts +49 -0
  73. package/dist/node/grant-store.d.ts.map +1 -0
  74. package/dist/node/grant-store.js +95 -0
  75. package/dist/node/grant-store.js.map +1 -0
  76. package/dist/node/grant-tools.d.ts +29 -0
  77. package/dist/node/grant-tools.d.ts.map +1 -0
  78. package/dist/node/grant-tools.js +498 -0
  79. package/dist/node/grant-tools.js.map +1 -0
  80. package/dist/node/ledger.d.ts +26 -0
  81. package/dist/node/ledger.d.ts.map +1 -0
  82. package/dist/node/ledger.js +78 -0
  83. package/dist/node/ledger.js.map +1 -0
  84. package/dist/node/payer.d.ts +48 -0
  85. package/dist/node/payer.d.ts.map +1 -0
  86. package/dist/node/payer.js +170 -0
  87. package/dist/node/payer.js.map +1 -0
  88. package/dist/node/resolve-input.d.ts +19 -0
  89. package/dist/node/resolve-input.d.ts.map +1 -0
  90. package/dist/node/resolve-input.js +76 -0
  91. package/dist/node/resolve-input.js.map +1 -0
  92. package/dist/node/server.d.ts +47 -0
  93. package/dist/node/server.d.ts.map +1 -0
  94. package/dist/node/server.js +212 -0
  95. package/dist/node/server.js.map +1 -0
  96. package/dist/node/signer-file.d.ts +34 -0
  97. package/dist/node/signer-file.d.ts.map +1 -0
  98. package/dist/node/signer-file.js +183 -0
  99. package/dist/node/signer-file.js.map +1 -0
  100. package/dist/node/store.d.ts +40 -0
  101. package/dist/node/store.d.ts.map +1 -0
  102. package/dist/node/store.js +117 -0
  103. package/dist/node/store.js.map +1 -0
  104. package/dist/node/text.d.ts +29 -0
  105. package/dist/node/text.d.ts.map +1 -0
  106. package/dist/node/text.js +124 -0
  107. package/dist/node/text.js.map +1 -0
  108. package/dist/node/tools.d.ts +118 -0
  109. package/dist/node/tools.d.ts.map +1 -0
  110. package/dist/node/tools.js +548 -0
  111. package/dist/node/tools.js.map +1 -0
  112. package/package.json +108 -3
  113. package/src/core/base64.ts +18 -0
  114. package/src/core/delegation.ts +239 -0
  115. package/src/core/grant.ts +127 -0
  116. package/src/core/hex.ts +18 -0
  117. package/src/core/index.ts +84 -0
  118. package/src/core/issue.ts +209 -0
  119. package/src/core/limits.ts +8 -0
  120. package/src/core/scrapi.ts +236 -0
  121. package/src/core/signer.ts +23 -0
  122. package/src/core/statement.ts +133 -0
  123. package/src/core/version.ts +25 -0
  124. package/src/core/x402.ts +314 -0
  125. package/src/net/delegate.ts +274 -0
  126. package/src/net/http.ts +71 -0
  127. package/src/net/index.ts +26 -0
  128. package/src/net/write.ts +124 -0
  129. package/src/node/cli.ts +170 -0
  130. package/src/node/grant-store.ts +154 -0
  131. package/src/node/grant-tools.ts +707 -0
  132. package/src/node/ledger.ts +98 -0
  133. package/src/node/payer.ts +241 -0
  134. package/src/node/resolve-input.ts +96 -0
  135. package/src/node/server.ts +332 -0
  136. package/src/node/signer-file.ts +251 -0
  137. package/src/node/store.ts +175 -0
  138. package/src/node/text.ts +153 -0
  139. package/src/node/tools.ts +810 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statement.js","sourceRoot":"","sources":["../../src/core/statement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Version strings, as literals.
3
+ *
4
+ * Not read from `package.json`: `src/core` is browser-safe, so it has no
5
+ * `node:fs`, and a JSON import would bake a resolveJsonModule edge into the
6
+ * `"."` bundle for a handful of strings. The MCP smoke test asserts
7
+ * `PACKAGE_VERSION === package.json#version`, so a forgotten bump is a red
8
+ * test rather than a silent lie in `initialize`'s serverInfo.
9
+ *
10
+ * Only the versions this package reports (`--help`, `initialize`) live here.
11
+ * Bump each one in the same commit as the dependency it names.
12
+ */
13
+ /** Keep in sync with package.json#version. Asserted by test/node/mcp-smoke. */
14
+ export declare const PACKAGE_VERSION = "0.1.1";
15
+ /** Keep in sync with package.json#dependencies["@forestrie/mcp-verify"] — the
16
+ * verifier this package composes with. Asserted by
17
+ * test/core/version.test.ts. */
18
+ export declare const VERIFIER_VERSION = "0.5.0";
19
+ /** Keep in sync with package.json#dependencies["@forestrie/mcp-resolve"] —
20
+ * the resolver this package composes with. Asserted by
21
+ * test/core/version.test.ts. */
22
+ export declare const RESOLVE_VERSION = "0.3.0";
23
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC;;iCAEiC;AACjC,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC;;iCAEiC;AACjC,eAAO,MAAM,eAAe,UAAU,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Version strings, as literals.
3
+ *
4
+ * Not read from `package.json`: `src/core` is browser-safe, so it has no
5
+ * `node:fs`, and a JSON import would bake a resolveJsonModule edge into the
6
+ * `"."` bundle for a handful of strings. The MCP smoke test asserts
7
+ * `PACKAGE_VERSION === package.json#version`, so a forgotten bump is a red
8
+ * test rather than a silent lie in `initialize`'s serverInfo.
9
+ *
10
+ * Only the versions this package reports (`--help`, `initialize`) live here.
11
+ * Bump each one in the same commit as the dependency it names.
12
+ */
13
+ /** Keep in sync with package.json#version. Asserted by test/node/mcp-smoke. */
14
+ export const PACKAGE_VERSION = "0.1.1";
15
+ /** Keep in sync with package.json#dependencies["@forestrie/mcp-verify"] — the
16
+ * verifier this package composes with. Asserted by
17
+ * test/core/version.test.ts. */
18
+ export const VERIFIER_VERSION = "0.5.0";
19
+ /** Keep in sync with package.json#dependencies["@forestrie/mcp-resolve"] —
20
+ * the resolver this package composes with. Asserted by
21
+ * test/core/version.test.ts. */
22
+ export const RESOLVE_VERSION = "0.3.0";
23
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC;;iCAEiC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC;;iCAEiC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * x402 over already-decoded JSON: read canopy's payment requirements, pick
3
+ * the one option this server may pay, and refuse anything outside its caps.
4
+ *
5
+ * canopy's register-grant gate (canopy `scrapi/register-grant-payment.ts`)
6
+ * answers a payment-gated child grant with 402 and an `X-PAYMENT-REQUIRED`
7
+ * header: base64 of x402 v2 `PaymentRequirements`
8
+ * (`{x402Version: 2, accepts: [{scheme: "exact", network, amount, asset,
9
+ * payTo, maxTimeoutSeconds, extra}], resource: {url, …}}`), priced as a
10
+ * unit price × the child grant's `maxHeight`. The retry carries
11
+ * `X-PAYMENT`: base64 of the x402 v2 `PaymentPayload` (an EIP-3009
12
+ * authorisation for the exact amount).
13
+ *
14
+ * The caps are the server's configuration, never a tool argument: a model
15
+ * (or whatever prompt-injected it) cannot raise them. Every amount is in the
16
+ * asset's atomic units.
17
+ */
18
+ export declare class PaymentError extends Error {
19
+ readonly code: "invalid_payment_requirements" | "invalid_payment" | CapRefusalCode;
20
+ constructor(code: "invalid_payment_requirements" | "invalid_payment" | CapRefusalCode, message: string);
21
+ }
22
+ export type CapRefusalCode = "cap_network" | "cap_asset" | "cap_testnet_only" | "cap_payee" | "cap_resource" | "cap_per_call" | "cap_per_day";
23
+ export interface PaymentOption {
24
+ scheme: "exact";
25
+ network: string;
26
+ amount: string;
27
+ asset: string;
28
+ payTo: string;
29
+ maxTimeoutSeconds?: number;
30
+ extra?: Record<string, unknown>;
31
+ }
32
+ export interface PaymentRequired {
33
+ x402Version: 2;
34
+ accepts: PaymentOption[];
35
+ resource?: {
36
+ url: string;
37
+ description?: string;
38
+ mimeType?: string;
39
+ };
40
+ error?: string;
41
+ }
42
+ /** Hard limits from the server's configuration. */
43
+ export interface PaymentCaps {
44
+ /** The one CAIP-2 network this server pays on, e.g. `eip155:84532`. */
45
+ network: string;
46
+ /** The one asset contract it pays in, lowercase `0x…`. */
47
+ asset: string;
48
+ maxPerCallAtomic: bigint;
49
+ maxPerDayAtomic: bigint;
50
+ /** When set, the only payee it pays. */
51
+ payTo?: string;
52
+ /** Pay on a network outside {@link TESTNETS}. Off by default. */
53
+ allowMainnet: boolean;
54
+ }
55
+ /** EVM testnets x402 facilitators settle on. Anything else is mainnet money. */
56
+ export declare const TESTNETS: ReadonlySet<string>;
57
+ /** Base Sepolia, and Circle's USDC on it: the network and asset canopy prices in. */
58
+ export declare const DEFAULT_PAY_NETWORK = "eip155:84532";
59
+ export declare const DEFAULT_PAY_ASSET = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
60
+ /** Validate decoded `X-PAYMENT-REQUIRED` JSON. Throws `PaymentError`. */
61
+ export declare function readPaymentRequired(json: unknown): PaymentRequired;
62
+ export interface CapContext {
63
+ /** The URL the payment is for: the register-grant URL this server POSTed. */
64
+ resourceUrl: string;
65
+ /** Atomic units already committed today (UTC), on this network and asset. */
66
+ spentTodayAtomic: bigint;
67
+ }
68
+ /**
69
+ * The one option this server may pay, or a `PaymentError` naming the cap
70
+ * that refuses it. Checked in the order a reader would ask: where, in what,
71
+ * to whom, for what, how much now, how much today.
72
+ */
73
+ export declare function selectWithinCaps(required: PaymentRequired, caps: PaymentCaps, ctx: CapContext): PaymentOption;
74
+ /** What an `X-PAYMENT` authorises, for reporting. Never includes the signature. */
75
+ export interface PaymentSummary {
76
+ network: string;
77
+ asset?: string;
78
+ from: string;
79
+ to: string;
80
+ value: string;
81
+ nonce: string;
82
+ validBefore: string;
83
+ }
84
+ /** Read decoded `X-PAYMENT` JSON (x402 v2 exact EVM). Throws `PaymentError`. */
85
+ export declare function readPaymentPayload(json: unknown): PaymentSummary;
86
+ /**
87
+ * The EIP-3009 nonce for paying for one grant: SHA-256 over a domain tag,
88
+ * the grant's content (its grant v0 CBOR, so a re-signed copy of the same
89
+ * grant gets the same nonce) and the payer's 20-byte address.
90
+ *
91
+ * EIP-3009 lets a token contract execute at most one authorisation per
92
+ * (payer, nonce), and canopy's claim and its settlement de-duplication are
93
+ * keyed by the nonce too. So every authorisation this payer ever signs for
94
+ * this grant shares one nonce, and at most one of them can settle: two
95
+ * overlapping calls, a retry after a lost answer, or a second process
96
+ * sharing the same payer cannot pay for the grant twice.
97
+ */
98
+ export declare function grantPaymentNonce(grantContent: Uint8Array, payerAddress: Uint8Array): Promise<string>;
99
+ //# sourceMappingURL=x402.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../src/core/x402.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,qBAAa,YAAa,SAAQ,KAAK;IAEnC,QAAQ,CAAC,IAAI,EACX,8BAA8B,GAAG,iBAAiB,GAAG,cAAc;gBAD5D,IAAI,EACX,8BAA8B,GAAG,iBAAiB,GAAG,cAAc,EACrE,OAAO,EAAE,MAAM;CAIlB;AAED,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,WAAW,GACX,kBAAkB,GAClB,WAAW,GACX,cAAc,GACd,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,CAAC,CAAC;IACf,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,gFAAgF;AAChF,eAAO,MAAM,QAAQ,EAAE,WAAW,CAAC,MAAM,CAOvC,CAAC;AAEH,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAS9E,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,CA8DlE;AAED,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,UAAU,GACd,aAAa,CAgDf;AAWD,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAgChE;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,UAAU,EACxB,YAAY,EAAE,UAAU,GACvB,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * x402 over already-decoded JSON: read canopy's payment requirements, pick
3
+ * the one option this server may pay, and refuse anything outside its caps.
4
+ *
5
+ * canopy's register-grant gate (canopy `scrapi/register-grant-payment.ts`)
6
+ * answers a payment-gated child grant with 402 and an `X-PAYMENT-REQUIRED`
7
+ * header: base64 of x402 v2 `PaymentRequirements`
8
+ * (`{x402Version: 2, accepts: [{scheme: "exact", network, amount, asset,
9
+ * payTo, maxTimeoutSeconds, extra}], resource: {url, …}}`), priced as a
10
+ * unit price × the child grant's `maxHeight`. The retry carries
11
+ * `X-PAYMENT`: base64 of the x402 v2 `PaymentPayload` (an EIP-3009
12
+ * authorisation for the exact amount).
13
+ *
14
+ * The caps are the server's configuration, never a tool argument: a model
15
+ * (or whatever prompt-injected it) cannot raise them. Every amount is in the
16
+ * asset's atomic units.
17
+ */
18
+ export class PaymentError extends Error {
19
+ code;
20
+ constructor(code, message) {
21
+ super(message);
22
+ this.code = code;
23
+ }
24
+ }
25
+ /** EVM testnets x402 facilitators settle on. Anything else is mainnet money. */
26
+ export const TESTNETS = new Set([
27
+ "eip155:84532", // Base Sepolia
28
+ "eip155:11155111", // Ethereum Sepolia
29
+ "eip155:421614", // Arbitrum Sepolia
30
+ "eip155:11155420", // OP Sepolia
31
+ "eip155:80002", // Polygon Amoy
32
+ "eip155:43113", // Avalanche Fuji
33
+ ]);
34
+ /** Base Sepolia, and Circle's USDC on it: the network and asset canopy prices in. */
35
+ export const DEFAULT_PAY_NETWORK = "eip155:84532";
36
+ export const DEFAULT_PAY_ASSET = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
37
+ const ATOMIC = /^[0-9]{1,78}$/;
38
+ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
39
+ function isObject(v) {
40
+ return typeof v === "object" && v !== null && !Array.isArray(v);
41
+ }
42
+ /** Validate decoded `X-PAYMENT-REQUIRED` JSON. Throws `PaymentError`. */
43
+ export function readPaymentRequired(json) {
44
+ const bad = (why) => new PaymentError("invalid_payment_requirements", `canopy's X-PAYMENT-REQUIRED is not x402 v2 payment requirements: ${why}`);
45
+ if (!isObject(json))
46
+ throw bad("not a JSON object");
47
+ if (json["x402Version"] !== 2)
48
+ throw bad("x402Version is not 2");
49
+ const accepts = json["accepts"];
50
+ if (!Array.isArray(accepts) || accepts.length === 0)
51
+ throw bad("accepts is empty");
52
+ const options = [];
53
+ for (const a of accepts) {
54
+ if (!isObject(a))
55
+ throw bad("an accepts entry is not an object");
56
+ const { scheme, network, amount, asset, payTo } = a;
57
+ if (typeof scheme !== "string" ||
58
+ typeof network !== "string" ||
59
+ typeof amount !== "string" ||
60
+ typeof asset !== "string" ||
61
+ typeof payTo !== "string")
62
+ throw bad("an accepts entry lacks scheme, network, amount, asset or payTo");
63
+ if (!ATOMIC.test(amount))
64
+ throw bad(`amount ${amount} is not an atomic-unit integer`);
65
+ if (!ADDRESS.test(asset) || !ADDRESS.test(payTo))
66
+ throw bad("asset and payTo must be 0x-prefixed 20-byte addresses");
67
+ if (scheme !== "exact")
68
+ continue; // the only scheme canopy offers
69
+ options.push({
70
+ scheme,
71
+ network,
72
+ amount,
73
+ asset,
74
+ payTo,
75
+ ...(typeof a["maxTimeoutSeconds"] === "number"
76
+ ? { maxTimeoutSeconds: a["maxTimeoutSeconds"] }
77
+ : {}),
78
+ ...(isObject(a["extra"]) ? { extra: a["extra"] } : {}),
79
+ });
80
+ }
81
+ if (options.length === 0)
82
+ throw bad('no accepts entry has scheme "exact"');
83
+ const resource = json["resource"];
84
+ return {
85
+ x402Version: 2,
86
+ accepts: options,
87
+ ...(isObject(resource) && typeof resource["url"] === "string"
88
+ ? {
89
+ resource: {
90
+ url: resource["url"],
91
+ ...(typeof resource["description"] === "string"
92
+ ? { description: resource["description"] }
93
+ : {}),
94
+ ...(typeof resource["mimeType"] === "string"
95
+ ? { mimeType: resource["mimeType"] }
96
+ : {}),
97
+ },
98
+ }
99
+ : {}),
100
+ ...(typeof json["error"] === "string" ? { error: json["error"] } : {}),
101
+ };
102
+ }
103
+ /**
104
+ * The one option this server may pay, or a `PaymentError` naming the cap
105
+ * that refuses it. Checked in the order a reader would ask: where, in what,
106
+ * to whom, for what, how much now, how much today.
107
+ */
108
+ export function selectWithinCaps(required, caps, ctx) {
109
+ const offered = (f) => [...new Set(required.accepts.map(f))].join(", ");
110
+ if (!TESTNETS.has(caps.network) && !caps.allowMainnet)
111
+ throw new PaymentError("cap_testnet_only", `the configured network ${caps.network} is not a testnet, and paying on a mainnet is off (set MCP_REGISTER_PAY_ALLOW_MAINNET=1 to allow it)`);
112
+ const onNetwork = required.accepts.filter((o) => o.network === caps.network);
113
+ if (onNetwork.length === 0)
114
+ throw new PaymentError("cap_network", `canopy asks for payment on ${offered((o) => o.network)}; this server pays only on ${caps.network}`);
115
+ const option = onNetwork.find((o) => o.asset.toLowerCase() === caps.asset);
116
+ if (option === undefined)
117
+ throw new PaymentError("cap_asset", `canopy asks for payment in ${offered((o) => o.asset)}; this server pays only in ${caps.asset}`);
118
+ if (caps.payTo !== undefined &&
119
+ option.payTo.toLowerCase() !== caps.payTo.toLowerCase())
120
+ throw new PaymentError("cap_payee", `canopy asks for payment to ${option.payTo}; this server pays only ${caps.payTo}`);
121
+ if (required.resource !== undefined &&
122
+ stripQuery(required.resource.url) !== stripQuery(ctx.resourceUrl))
123
+ throw new PaymentError("cap_resource", `the payment requirements are for ${required.resource.url}, not the request this server made (${ctx.resourceUrl})`);
124
+ const amount = BigInt(option.amount);
125
+ if (amount > caps.maxPerCallAtomic)
126
+ throw new PaymentError("cap_per_call", `canopy asks ${option.amount} atomic units; this server's per-call cap is ${caps.maxPerCallAtomic}. Issue a grant with a smaller maxHeight, or pay in relay mode from a wallet you control`);
127
+ if (ctx.spentTodayAtomic + amount > caps.maxPerDayAtomic)
128
+ throw new PaymentError("cap_per_day", `paying ${option.amount} would bring today's (UTC) spend to ${ctx.spentTodayAtomic + amount} atomic units; this server's daily cap is ${caps.maxPerDayAtomic}`);
129
+ return option;
130
+ }
131
+ function stripQuery(url) {
132
+ try {
133
+ const u = new URL(url);
134
+ return `${u.origin}${u.pathname}`;
135
+ }
136
+ catch {
137
+ return url;
138
+ }
139
+ }
140
+ /** Read decoded `X-PAYMENT` JSON (x402 v2 exact EVM). Throws `PaymentError`. */
141
+ export function readPaymentPayload(json) {
142
+ const bad = (why) => new PaymentError("invalid_payment", `the payment is not an x402 v2 exact EVM payment payload: ${why}`);
143
+ if (!isObject(json))
144
+ throw bad("not a JSON object");
145
+ if (json["x402Version"] !== 2 && json["x402Version"] !== 1)
146
+ throw bad("x402Version is not 1 or 2");
147
+ const accepted = isObject(json["accepted"]) ? json["accepted"] : json;
148
+ const payload = json["payload"];
149
+ if (!isObject(payload))
150
+ throw bad("payload is missing");
151
+ const auth = payload["authorization"];
152
+ if (!isObject(auth))
153
+ throw bad("payload.authorization is missing");
154
+ const field = (k) => {
155
+ const v = auth[k];
156
+ if (typeof v !== "string")
157
+ throw bad(`authorization.${k} is missing`);
158
+ return v;
159
+ };
160
+ const network = accepted["network"];
161
+ if (typeof network !== "string")
162
+ throw bad("network is missing");
163
+ return {
164
+ network,
165
+ ...(typeof accepted["asset"] === "string"
166
+ ? { asset: accepted["asset"] }
167
+ : {}),
168
+ from: field("from"),
169
+ to: field("to"),
170
+ value: field("value"),
171
+ nonce: field("nonce"),
172
+ validBefore: field("validBefore"),
173
+ };
174
+ }
175
+ const NONCE_TAG = new TextEncoder().encode("forestrie/mcp-register x402 grant payment nonce v1");
176
+ /**
177
+ * The EIP-3009 nonce for paying for one grant: SHA-256 over a domain tag,
178
+ * the grant's content (its grant v0 CBOR, so a re-signed copy of the same
179
+ * grant gets the same nonce) and the payer's 20-byte address.
180
+ *
181
+ * EIP-3009 lets a token contract execute at most one authorisation per
182
+ * (payer, nonce), and canopy's claim and its settlement de-duplication are
183
+ * keyed by the nonce too. So every authorisation this payer ever signs for
184
+ * this grant shares one nonce, and at most one of them can settle: two
185
+ * overlapping calls, a retry after a lost answer, or a second process
186
+ * sharing the same payer cannot pay for the grant twice.
187
+ */
188
+ export async function grantPaymentNonce(grantContent, payerAddress) {
189
+ if (payerAddress.length !== 20)
190
+ throw new PaymentError("invalid_payment", `the payer address must be 20 bytes (got ${payerAddress.length})`);
191
+ const content = new Uint8Array(await crypto.subtle.digest("SHA-256", grantContent));
192
+ const material = new Uint8Array(NONCE_TAG.length + 1 + 32 + 20);
193
+ material.set(NONCE_TAG, 0);
194
+ material.set(content, NONCE_TAG.length + 1);
195
+ material.set(payerAddress, NONCE_TAG.length + 33);
196
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", material));
197
+ let hex = "0x";
198
+ for (const b of digest)
199
+ hex += b.toString(16).padStart(2, "0");
200
+ return hex;
201
+ }
202
+ //# sourceMappingURL=x402.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.js","sourceRoot":"","sources":["../../src/core/x402.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Delegate sealing for the caller's data log, falling back to `prepare`.
3
+ *
4
+ * 1. GET pending-delegation. A standing entry means the coordinator knows
5
+ * the log's public root and has a vouched sealer key for it.
6
+ * 2. No standing entry: the coordinator never learned the root. canopy
7
+ * forwards it at register-grant, best effort; `POST
8
+ * /api/forest/{child}/prepare` under the same creation grant does it
9
+ * explicitly. Then poll pending-delegation again, a bounded number of
10
+ * times.
11
+ * 3. Verify the registrar voucher against the pinned sealer key, build the
12
+ * certificate and on-chain proof with the log key, and submit them.
13
+ *
14
+ * Each failure names its stage, so the caller can tell "prepare refused the
15
+ * grant" from "the coordinator rejected the certificate".
16
+ */
17
+ import type { FetchOptions } from "@forestrie/mcp-resolve/net";
18
+ import { type GrantView } from "../core/grant.js";
19
+ import { type Problem } from "../core/scrapi.js";
20
+ import type { Es256Signer } from "../core/signer.js";
21
+ export type DelegateStage = "pending_delegation" | "prepare" | "voucher" | "certificate";
22
+ export interface DelegateSealingInput {
23
+ baseUrl: string;
24
+ coordinatorUrl: string;
25
+ /** The registrar's voucher key, 64 bytes x‖y, pinned out of band. */
26
+ knownSealerKeyXY: Uint8Array;
27
+ grantB64: string;
28
+ grant: GrantView;
29
+ mmrEnd?: number;
30
+ ttlSeconds?: number;
31
+ /** Polls of pending-delegation after a successful prepare. Default 5. */
32
+ pollsAfterPrepare?: number;
33
+ /** Wait between those polls, ms. Default 2000. */
34
+ pollIntervalMs?: number;
35
+ sleep?: (ms: number) => Promise<void>;
36
+ }
37
+ export type DelegateSealingOutcome = {
38
+ kind: "delegated";
39
+ logId: string;
40
+ sealerId: string;
41
+ epoch: number;
42
+ mmrEnd: number;
43
+ issuedAt: number;
44
+ expiresAt: number;
45
+ /** True when this call had to run prepare first. */
46
+ prepared: boolean;
47
+ certificateKey?: string;
48
+ } | {
49
+ kind: "problem";
50
+ stage: DelegateStage;
51
+ message: string;
52
+ problem?: Problem;
53
+ prepared: boolean;
54
+ };
55
+ export declare function delegateSealing(input: DelegateSealingInput, signer: Es256Signer, opts?: FetchOptions): Promise<DelegateSealingOutcome>;
56
+ //# sourceMappingURL=delegate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../src/net/delegate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS/D,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOrD,MAAM,MAAM,aAAa,GACvB,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,gBAAgB,EAAE,UAAU,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,sBAAsB,GAC9B;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAKN,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,WAAW,EACnB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAqKjC"}
@@ -0,0 +1,182 @@
1
+ import { buildCertificateSubmission, checkVoucher, DelegationError, findStandingEntry, } from "../core/delegation.js";
2
+ import { prepareGrantProblems } from "../core/grant.js";
3
+ import { readProblem } from "../core/scrapi.js";
4
+ import { getPendingDelegation, postDelegationCertificate, prepareChildLog, } from "./write.js";
5
+ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
+ export async function delegateSealing(input, signer, opts) {
7
+ const logId = input.grant.logId;
8
+ let prepared = false;
9
+ const readStanding = async () => {
10
+ const res = await getPendingDelegation({ coordinatorUrl: input.coordinatorUrl, logId }, opts);
11
+ if (res.status !== 200)
12
+ return {
13
+ ok: false,
14
+ outcome: {
15
+ kind: "problem",
16
+ stage: "pending_delegation",
17
+ message: `pending-delegation answered HTTP ${res.status}`,
18
+ problem: readJsonProblem(res.status, res.body),
19
+ prepared,
20
+ },
21
+ };
22
+ let body;
23
+ try {
24
+ body = JSON.parse(new TextDecoder().decode(res.body));
25
+ }
26
+ catch {
27
+ return {
28
+ ok: false,
29
+ outcome: {
30
+ kind: "problem",
31
+ stage: "pending_delegation",
32
+ message: "pending-delegation did not return JSON",
33
+ prepared,
34
+ },
35
+ };
36
+ }
37
+ try {
38
+ return { ok: true, standing: findStandingEntry(body) };
39
+ }
40
+ catch (err) {
41
+ return {
42
+ ok: false,
43
+ outcome: {
44
+ kind: "problem",
45
+ stage: err instanceof DelegationError && err.code === "voucher_rejected"
46
+ ? "voucher"
47
+ : "pending_delegation",
48
+ message: err.message,
49
+ prepared,
50
+ },
51
+ };
52
+ }
53
+ };
54
+ let read = await readStanding();
55
+ if (!read.ok)
56
+ return read.outcome;
57
+ if (read.standing === undefined) {
58
+ const refusals = prepareGrantProblems(input.grant);
59
+ if (refusals.length > 0)
60
+ return {
61
+ kind: "problem",
62
+ stage: "prepare",
63
+ message: `the coordinator has no standing sealer key for log ${logId} (its public root was never forwarded), and prepare cannot fix that with this grant: ${refusals.join("; ")}`,
64
+ prepared,
65
+ };
66
+ const res = await prepareChildLog({ baseUrl: input.baseUrl, logId, grantB64: input.grantB64 }, opts);
67
+ if (res.status < 200 || res.status >= 300)
68
+ return {
69
+ kind: "problem",
70
+ stage: "prepare",
71
+ message: `prepare answered HTTP ${res.status}`,
72
+ problem: readProblem(res),
73
+ prepared,
74
+ };
75
+ prepared = true;
76
+ const sleep = input.sleep ?? defaultSleep;
77
+ const polls = input.pollsAfterPrepare ?? 5;
78
+ for (let i = 0; i < polls; i++) {
79
+ await sleep(input.pollIntervalMs ?? 2000);
80
+ read = await readStanding();
81
+ if (!read.ok)
82
+ return read.outcome;
83
+ if (read.standing !== undefined)
84
+ break;
85
+ }
86
+ if (read.standing === undefined)
87
+ return {
88
+ kind: "problem",
89
+ stage: "pending_delegation",
90
+ message: `prepare succeeded, but after ${polls} polls the coordinator still offers no standing sealer key for log ${logId}; try delegate_sealing again shortly`,
91
+ prepared,
92
+ };
93
+ }
94
+ const standing = read.standing;
95
+ try {
96
+ await checkVoucher(standing, input.knownSealerKeyXY);
97
+ }
98
+ catch (err) {
99
+ return {
100
+ kind: "problem",
101
+ stage: "voucher",
102
+ message: err.message,
103
+ prepared,
104
+ };
105
+ }
106
+ let submission;
107
+ try {
108
+ submission = await buildCertificateSubmission({
109
+ logId,
110
+ standing,
111
+ ...(input.mmrEnd !== undefined ? { mmrEnd: input.mmrEnd } : {}),
112
+ ...(input.ttlSeconds !== undefined
113
+ ? { ttlSeconds: input.ttlSeconds }
114
+ : {}),
115
+ }, signer);
116
+ }
117
+ catch (err) {
118
+ // A malformed standing key, a bad ttl or a signer failure: report it
119
+ // at its stage rather than as a raw throw.
120
+ return {
121
+ kind: "problem",
122
+ stage: "certificate",
123
+ message: `could not build the delegation certificate: ${err instanceof Error ? err.message : String(err)}`,
124
+ prepared,
125
+ };
126
+ }
127
+ const res = await postDelegationCertificate({ coordinatorUrl: input.coordinatorUrl, submission }, opts);
128
+ if (res.status < 200 || res.status >= 300)
129
+ return {
130
+ kind: "problem",
131
+ stage: "certificate",
132
+ message: `the coordinator rejected the delegation certificate: HTTP ${res.status}`,
133
+ problem: readJsonProblem(res.status, res.body),
134
+ prepared,
135
+ };
136
+ let certificateKey;
137
+ try {
138
+ const body = JSON.parse(new TextDecoder().decode(res.body));
139
+ if (typeof body.certificateKey === "string")
140
+ certificateKey = body.certificateKey;
141
+ }
142
+ catch {
143
+ // A 2xx without a JSON body still means accepted.
144
+ }
145
+ return {
146
+ kind: "delegated",
147
+ logId,
148
+ sealerId: standing.sealerId,
149
+ epoch: standing.epoch,
150
+ mmrEnd: submission.mmrEnd,
151
+ issuedAt: submission.issuedAt,
152
+ expiresAt: submission.expiresAt,
153
+ prepared,
154
+ ...(certificateKey !== undefined ? { certificateKey } : {}),
155
+ };
156
+ }
157
+ function readJsonProblem(status, body) {
158
+ const text = new TextDecoder().decode(body);
159
+ try {
160
+ const parsed = JSON.parse(text);
161
+ const title = typeof parsed.title === "string"
162
+ ? parsed.title
163
+ : typeof parsed.error === "string"
164
+ ? parsed.error
165
+ : `HTTP ${status}`;
166
+ const detail = typeof parsed.detail === "string"
167
+ ? parsed.detail
168
+ : typeof parsed.message === "string"
169
+ ? parsed.message
170
+ : undefined;
171
+ return { status, title, ...(detail !== undefined ? { detail } : {}) };
172
+ }
173
+ catch {
174
+ const printable = text.replace(/[^\x20-\x7e]+/g, " ").trim();
175
+ return {
176
+ status,
177
+ title: `HTTP ${status}`,
178
+ ...(printable ? { detail: printable.slice(0, 500) } : {}),
179
+ };
180
+ }
181
+ }
182
+ //# sourceMappingURL=delegate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../src/net/delegate.ts"],"names":[],"mappings":"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"}