@shroud-fi/mcp-server 0.1.0

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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/dist/cjs/auth.d.ts +41 -0
  4. package/dist/cjs/auth.d.ts.map +1 -0
  5. package/dist/cjs/auth.js +103 -0
  6. package/dist/cjs/auth.js.map +1 -0
  7. package/dist/cjs/bin/http.d.ts +7 -0
  8. package/dist/cjs/bin/http.d.ts.map +1 -0
  9. package/dist/cjs/bin/http.js +24 -0
  10. package/dist/cjs/bin/http.js.map +1 -0
  11. package/dist/cjs/bin/stdio.d.ts +9 -0
  12. package/dist/cjs/bin/stdio.d.ts.map +1 -0
  13. package/dist/cjs/bin/stdio.js +15 -0
  14. package/dist/cjs/bin/stdio.js.map +1 -0
  15. package/dist/cjs/config.d.ts +22 -0
  16. package/dist/cjs/config.d.ts.map +1 -0
  17. package/dist/cjs/config.js +180 -0
  18. package/dist/cjs/config.js.map +1 -0
  19. package/dist/cjs/constants.d.ts +29 -0
  20. package/dist/cjs/constants.d.ts.map +1 -0
  21. package/dist/cjs/constants.js +35 -0
  22. package/dist/cjs/constants.js.map +1 -0
  23. package/dist/cjs/errors.d.ts +43 -0
  24. package/dist/cjs/errors.d.ts.map +1 -0
  25. package/dist/cjs/errors.js +72 -0
  26. package/dist/cjs/errors.js.map +1 -0
  27. package/dist/cjs/http.d.ts +32 -0
  28. package/dist/cjs/http.d.ts.map +1 -0
  29. package/dist/cjs/http.js +180 -0
  30. package/dist/cjs/http.js.map +1 -0
  31. package/dist/cjs/index.d.ts +19 -0
  32. package/dist/cjs/index.d.ts.map +1 -0
  33. package/dist/cjs/index.js +40 -0
  34. package/dist/cjs/index.js.map +1 -0
  35. package/dist/cjs/package.json +1 -0
  36. package/dist/cjs/server.d.ts +14 -0
  37. package/dist/cjs/server.d.ts.map +1 -0
  38. package/dist/cjs/server.js +92 -0
  39. package/dist/cjs/server.js.map +1 -0
  40. package/dist/cjs/stdio.d.ts +9 -0
  41. package/dist/cjs/stdio.d.ts.map +1 -0
  42. package/dist/cjs/stdio.js +21 -0
  43. package/dist/cjs/stdio.js.map +1 -0
  44. package/dist/cjs/tools/balance.d.ts +9 -0
  45. package/dist/cjs/tools/balance.d.ts.map +1 -0
  46. package/dist/cjs/tools/balance.js +61 -0
  47. package/dist/cjs/tools/balance.js.map +1 -0
  48. package/dist/cjs/tools/index.d.ts +17 -0
  49. package/dist/cjs/tools/index.d.ts.map +1 -0
  50. package/dist/cjs/tools/index.js +40 -0
  51. package/dist/cjs/tools/index.js.map +1 -0
  52. package/dist/cjs/tools/receive.d.ts +13 -0
  53. package/dist/cjs/tools/receive.d.ts.map +1 -0
  54. package/dist/cjs/tools/receive.js +100 -0
  55. package/dist/cjs/tools/receive.js.map +1 -0
  56. package/dist/cjs/tools/register.d.ts +9 -0
  57. package/dist/cjs/tools/register.d.ts.map +1 -0
  58. package/dist/cjs/tools/register.js +36 -0
  59. package/dist/cjs/tools/register.js.map +1 -0
  60. package/dist/cjs/tools/schema.d.ts +18 -0
  61. package/dist/cjs/tools/schema.d.ts.map +1 -0
  62. package/dist/cjs/tools/schema.js +25 -0
  63. package/dist/cjs/tools/schema.js.map +1 -0
  64. package/dist/cjs/tools/send-to-wallet.d.ts +9 -0
  65. package/dist/cjs/tools/send-to-wallet.d.ts.map +1 -0
  66. package/dist/cjs/tools/send-to-wallet.js +60 -0
  67. package/dist/cjs/tools/send-to-wallet.js.map +1 -0
  68. package/dist/cjs/tools/send.d.ts +9 -0
  69. package/dist/cjs/tools/send.d.ts.map +1 -0
  70. package/dist/cjs/tools/send.js +68 -0
  71. package/dist/cjs/tools/send.js.map +1 -0
  72. package/dist/cjs/tools/status.d.ts +6 -0
  73. package/dist/cjs/tools/status.d.ts.map +1 -0
  74. package/dist/cjs/tools/status.js +39 -0
  75. package/dist/cjs/tools/status.js.map +1 -0
  76. package/dist/cjs/tools/sweep.d.ts +14 -0
  77. package/dist/cjs/tools/sweep.d.ts.map +1 -0
  78. package/dist/cjs/tools/sweep.js +119 -0
  79. package/dist/cjs/tools/sweep.js.map +1 -0
  80. package/dist/cjs/tools/x402-pay.d.ts +14 -0
  81. package/dist/cjs/tools/x402-pay.d.ts.map +1 -0
  82. package/dist/cjs/tools/x402-pay.js +78 -0
  83. package/dist/cjs/tools/x402-pay.js.map +1 -0
  84. package/dist/cjs/tools/x402-serve.d.ts +17 -0
  85. package/dist/cjs/tools/x402-serve.d.ts.map +1 -0
  86. package/dist/cjs/tools/x402-serve.js +133 -0
  87. package/dist/cjs/tools/x402-serve.js.map +1 -0
  88. package/dist/cjs/types.d.ts +66 -0
  89. package/dist/cjs/types.d.ts.map +1 -0
  90. package/dist/cjs/types.js +6 -0
  91. package/dist/cjs/types.js.map +1 -0
  92. package/dist/esm/auth.d.ts +41 -0
  93. package/dist/esm/auth.d.ts.map +1 -0
  94. package/dist/esm/auth.js +99 -0
  95. package/dist/esm/auth.js.map +1 -0
  96. package/dist/esm/bin/http.d.ts +7 -0
  97. package/dist/esm/bin/http.d.ts.map +1 -0
  98. package/dist/esm/bin/http.js +22 -0
  99. package/dist/esm/bin/http.js.map +1 -0
  100. package/dist/esm/bin/stdio.d.ts +9 -0
  101. package/dist/esm/bin/stdio.d.ts.map +1 -0
  102. package/dist/esm/bin/stdio.js +13 -0
  103. package/dist/esm/bin/stdio.js.map +1 -0
  104. package/dist/esm/config.d.ts +22 -0
  105. package/dist/esm/config.d.ts.map +1 -0
  106. package/dist/esm/config.js +175 -0
  107. package/dist/esm/config.js.map +1 -0
  108. package/dist/esm/constants.d.ts +29 -0
  109. package/dist/esm/constants.d.ts.map +1 -0
  110. package/dist/esm/constants.js +32 -0
  111. package/dist/esm/constants.js.map +1 -0
  112. package/dist/esm/errors.d.ts +43 -0
  113. package/dist/esm/errors.d.ts.map +1 -0
  114. package/dist/esm/errors.js +61 -0
  115. package/dist/esm/errors.js.map +1 -0
  116. package/dist/esm/http.d.ts +32 -0
  117. package/dist/esm/http.d.ts.map +1 -0
  118. package/dist/esm/http.js +177 -0
  119. package/dist/esm/http.js.map +1 -0
  120. package/dist/esm/index.d.ts +19 -0
  121. package/dist/esm/index.d.ts.map +1 -0
  122. package/dist/esm/index.js +18 -0
  123. package/dist/esm/index.js.map +1 -0
  124. package/dist/esm/server.d.ts +14 -0
  125. package/dist/esm/server.d.ts.map +1 -0
  126. package/dist/esm/server.js +89 -0
  127. package/dist/esm/server.js.map +1 -0
  128. package/dist/esm/stdio.d.ts +9 -0
  129. package/dist/esm/stdio.d.ts.map +1 -0
  130. package/dist/esm/stdio.js +18 -0
  131. package/dist/esm/stdio.js.map +1 -0
  132. package/dist/esm/tools/balance.d.ts +9 -0
  133. package/dist/esm/tools/balance.d.ts.map +1 -0
  134. package/dist/esm/tools/balance.js +58 -0
  135. package/dist/esm/tools/balance.js.map +1 -0
  136. package/dist/esm/tools/index.d.ts +17 -0
  137. package/dist/esm/tools/index.d.ts.map +1 -0
  138. package/dist/esm/tools/index.js +28 -0
  139. package/dist/esm/tools/index.js.map +1 -0
  140. package/dist/esm/tools/receive.d.ts +13 -0
  141. package/dist/esm/tools/receive.d.ts.map +1 -0
  142. package/dist/esm/tools/receive.js +97 -0
  143. package/dist/esm/tools/receive.js.map +1 -0
  144. package/dist/esm/tools/register.d.ts +9 -0
  145. package/dist/esm/tools/register.d.ts.map +1 -0
  146. package/dist/esm/tools/register.js +33 -0
  147. package/dist/esm/tools/register.js.map +1 -0
  148. package/dist/esm/tools/schema.d.ts +18 -0
  149. package/dist/esm/tools/schema.d.ts.map +1 -0
  150. package/dist/esm/tools/schema.js +21 -0
  151. package/dist/esm/tools/schema.js.map +1 -0
  152. package/dist/esm/tools/send-to-wallet.d.ts +9 -0
  153. package/dist/esm/tools/send-to-wallet.d.ts.map +1 -0
  154. package/dist/esm/tools/send-to-wallet.js +57 -0
  155. package/dist/esm/tools/send-to-wallet.js.map +1 -0
  156. package/dist/esm/tools/send.d.ts +9 -0
  157. package/dist/esm/tools/send.d.ts.map +1 -0
  158. package/dist/esm/tools/send.js +65 -0
  159. package/dist/esm/tools/send.js.map +1 -0
  160. package/dist/esm/tools/status.d.ts +6 -0
  161. package/dist/esm/tools/status.d.ts.map +1 -0
  162. package/dist/esm/tools/status.js +36 -0
  163. package/dist/esm/tools/status.js.map +1 -0
  164. package/dist/esm/tools/sweep.d.ts +14 -0
  165. package/dist/esm/tools/sweep.d.ts.map +1 -0
  166. package/dist/esm/tools/sweep.js +116 -0
  167. package/dist/esm/tools/sweep.js.map +1 -0
  168. package/dist/esm/tools/x402-pay.d.ts +14 -0
  169. package/dist/esm/tools/x402-pay.d.ts.map +1 -0
  170. package/dist/esm/tools/x402-pay.js +75 -0
  171. package/dist/esm/tools/x402-pay.js.map +1 -0
  172. package/dist/esm/tools/x402-serve.d.ts +17 -0
  173. package/dist/esm/tools/x402-serve.d.ts.map +1 -0
  174. package/dist/esm/tools/x402-serve.js +130 -0
  175. package/dist/esm/tools/x402-serve.js.map +1 -0
  176. package/dist/esm/types.d.ts +66 -0
  177. package/dist/esm/types.d.ts.map +1 -0
  178. package/dist/esm/types.js +5 -0
  179. package/dist/esm/types.js.map +1 -0
  180. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  181. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  182. package/dist/tsconfig.tsbuildinfo +1 -0
  183. package/package.json +81 -0
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * shroud_sweep — sweep a previously-detected stealth address to a destination.
4
+ *
5
+ * Caller passes the detection bundle returned by shroud_receive (stealth
6
+ * address + stealth private key + ephemeral pub key + tx coords). We
7
+ * reconstruct a minimal DetectedPayment and dispatch to agent.sweep.
8
+ *
9
+ * Optional flags:
10
+ * - viaRelayer + token → Gelato ERC-20 gasless sweep
11
+ * - viaRelayer (ETH) → EIP-7702 ETH gasless sweep (requires selfHostEndpoint)
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.shroudSweepTool = void 0;
15
+ const zod_1 = require("zod");
16
+ const errors_js_1 = require("../errors.js");
17
+ const schema_js_1 = require("./schema.js");
18
+ const HexSchema = zod_1.z.string().regex(/^0x[0-9a-fA-F]+$/);
19
+ const Hex32Schema = zod_1.z.string().regex(/^0x[0-9a-fA-F]{64}$/);
20
+ const ArgsSchema = zod_1.z
21
+ .object({
22
+ detection: zod_1.z.object({
23
+ stealthAddress: schema_js_1.AddressSchema,
24
+ ephemeralPubKey: HexSchema,
25
+ stealthPrivateKey: Hex32Schema,
26
+ txHash: Hex32Schema,
27
+ blockNumber: schema_js_1.Uint256StringSchema,
28
+ blockHash: Hex32Schema,
29
+ logIndex: zod_1.z.number().int().nonnegative(),
30
+ finality: zod_1.z.enum(['safe', 'finalized']).optional(),
31
+ }),
32
+ destination: schema_js_1.AddressSchema,
33
+ token: schema_js_1.AddressSchema.optional(),
34
+ viaRelayer: zod_1.z.boolean().optional(),
35
+ ethRelayerEndpoint: zod_1.z.string().url().optional(),
36
+ })
37
+ .strict();
38
+ exports.shroudSweepTool = {
39
+ name: 'shroud_sweep',
40
+ description: 'Sweep a detected stealth address to a destination wallet. Pass the detection object returned by shroud_receive. Omit `token` for ETH; pass `token` for an ERC-20. Set `viaRelayer: true` for gasless sweep (ERC-20 → Gelato; ETH → requires `ethRelayerEndpoint` to a self-host relayer).',
41
+ inputSchema: {
42
+ type: 'object',
43
+ additionalProperties: false,
44
+ properties: {
45
+ detection: {
46
+ type: 'object',
47
+ additionalProperties: false,
48
+ properties: {
49
+ stealthAddress: { type: 'string', pattern: '^0x[0-9a-fA-F]{40}$' },
50
+ ephemeralPubKey: { type: 'string', pattern: '^0x[0-9a-fA-F]+$' },
51
+ stealthPrivateKey: { type: 'string', pattern: '^0x[0-9a-fA-F]{64}$' },
52
+ txHash: { type: 'string', pattern: '^0x[0-9a-fA-F]{64}$' },
53
+ blockNumber: { type: 'string', pattern: '^\\d+$' },
54
+ blockHash: { type: 'string', pattern: '^0x[0-9a-fA-F]{64}$' },
55
+ logIndex: { type: 'integer', minimum: 0 },
56
+ finality: { type: 'string', enum: ['safe', 'finalized'] },
57
+ },
58
+ required: [
59
+ 'stealthAddress',
60
+ 'ephemeralPubKey',
61
+ 'stealthPrivateKey',
62
+ 'txHash',
63
+ 'blockNumber',
64
+ 'blockHash',
65
+ 'logIndex',
66
+ ],
67
+ },
68
+ destination: { type: 'string', pattern: '^0x[0-9a-fA-F]{40}$' },
69
+ token: { type: 'string', pattern: '^0x[0-9a-fA-F]{40}$' },
70
+ viaRelayer: { type: 'boolean' },
71
+ ethRelayerEndpoint: { type: 'string' },
72
+ },
73
+ required: ['detection', 'destination'],
74
+ },
75
+ async handler(ctx, raw) {
76
+ const parsed = ArgsSchema.safeParse(raw);
77
+ if (!parsed.success) {
78
+ throw new errors_js_1.McpInvalidArgsError();
79
+ }
80
+ const { detection, destination, token, viaRelayer, ethRelayerEndpoint } = parsed.data;
81
+ const dp = {
82
+ stealthAddress: detection.stealthAddress,
83
+ ephemeralPubKey: detection.ephemeralPubKey,
84
+ stealthPrivateKey: detection.stealthPrivateKey,
85
+ txHash: detection.txHash,
86
+ blockNumber: (0, schema_js_1.toBigInt)(detection.blockNumber),
87
+ blockHash: detection.blockHash,
88
+ logIndex: detection.logIndex,
89
+ finality: detection.finality ?? 'safe',
90
+ };
91
+ const sweepOpts = {};
92
+ if (token !== undefined)
93
+ sweepOpts.token = token;
94
+ if (viaRelayer === true) {
95
+ sweepOpts.viaRelayer = true;
96
+ if (ethRelayerEndpoint !== undefined) {
97
+ sweepOpts.ethRelayerOptions = { selfHostEndpoint: ethRelayerEndpoint };
98
+ }
99
+ }
100
+ const result = await ctx.agent.sweep(dp, destination, sweepOpts);
101
+ const swept = result.swept;
102
+ const out = {
103
+ ok: true,
104
+ txHash: swept.txHash,
105
+ destination: swept.destination,
106
+ };
107
+ if (swept.token !== undefined)
108
+ out.token = swept.token;
109
+ if (swept.blockNumber !== undefined) {
110
+ out.blockNumber = swept.blockNumber.toString();
111
+ }
112
+ if (swept.taskId !== undefined)
113
+ out.taskId = swept.taskId;
114
+ if (swept.status !== undefined)
115
+ out.status = swept.status;
116
+ return out;
117
+ },
118
+ };
119
+ //# sourceMappingURL=sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../../src/tools/sweep.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,6BAAwB;AAGxB,4CAAmD;AACnD,2CAA2E;AAE3E,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;AACvD,MAAM,WAAW,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAE5D,MAAM,UAAU,GAAG,OAAC;KACjB,MAAM,CAAC;IACN,SAAS,EAAE,OAAC,CAAC,MAAM,CAAC;QAClB,cAAc,EAAE,yBAAa;QAC7B,eAAe,EAAE,SAAS;QAC1B,iBAAiB,EAAE,WAAW;QAC9B,MAAM,EAAE,WAAW;QACnB,WAAW,EAAE,+BAAmB;QAChC,SAAS,EAAE,WAAW;QACtB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QACxC,QAAQ,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE;KACnD,CAAC;IACF,WAAW,EAAE,yBAAa;IAC1B,KAAK,EAAE,yBAAa,CAAC,QAAQ,EAAE;IAC/B,UAAU,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAClC,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAChD,CAAC;KACD,MAAM,EAAE,CAAC;AAEC,QAAA,eAAe,GAAY;IACtC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,2RAA2R;IAC7R,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE;YACV,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,UAAU,EAAE;oBACV,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;oBAClE,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE;oBAChE,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;oBACrE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;oBAC1D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE;oBAClD,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;oBAC7D,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;oBACzC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;iBAC1D;gBACD,QAAQ,EAAE;oBACR,gBAAgB;oBAChB,iBAAiB;oBACjB,mBAAmB;oBACnB,QAAQ;oBACR,aAAa;oBACb,WAAW;oBACX,UAAU;iBACX;aACF;YACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;YAC/D,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE;YACzD,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;YAC/B,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SACvC;QACD,QAAQ,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC;KACvC;IACD,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG;QACpB,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,+BAAmB,EAAE,CAAC;QAClC,CAAC;QACD,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;QAEtF,MAAM,EAAE,GAAoB;YAC1B,cAAc,EAAE,SAAS,CAAC,cAA+B;YACzD,eAAe,EAAE,SAAS,CAAC,eAAgC;YAC3D,iBAAiB,EAAE,SAAS,CAAC,iBAAkC;YAC/D,MAAM,EAAE,SAAS,CAAC,MAAuB;YACzC,WAAW,EAAE,IAAA,oBAAQ,EAAC,SAAS,CAAC,WAAW,CAAC;YAC5C,SAAS,EAAE,SAAS,CAAC,SAA0B;YAC/C,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,MAAM;SACvC,CAAC;QAEF,MAAM,SAAS,GAA0C,EAAE,CAAC;QAC5D,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS,CAAC,KAAK,GAAG,KAAsB,CAAC;QAClE,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;YAC5B,IAAI,kBAAkB,KAAK,SAAS,EAAE,CAAC;gBACrC,SAAS,CAAC,iBAAiB,GAAG,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;YACzE,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAClC,EAAE,EACF,WAA4B,EAC5B,SAAS,CACV,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAgC,CAAC;QACtD,MAAM,GAAG,GAA4B;YACnC,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC;QACF,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACvD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACpC,GAAG,CAAC,WAAW,GAAI,KAAK,CAAC,WAAsB,CAAC,QAAQ,EAAE,CAAC;QAC7D,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1D,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1D,OAAO,GAAoB,CAAC;IAC9B,CAAC;CACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * shroud_x402_pay — one-shot HTTP 402 client.
3
+ *
4
+ * Fetches a URL; if the server responds 402, the SDK signs an EIP-3009
5
+ * USDC transferWithAuthorization and retries automatically. Returns the
6
+ * server's final status, the body (if JSON-decodable), and the settled
7
+ * tx hash exposed via X-PAYMENT-RESPONSE when present.
8
+ *
9
+ * `maxPriceUsdcAtomic` is a hard safety cap. If the server demands more,
10
+ * the SDK throws X402AmountMismatchError without signing.
11
+ */
12
+ import type { McpTool } from '../types.js';
13
+ export declare const shroudX402PayTool: McpTool;
14
+ //# sourceMappingURL=x402-pay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402-pay.d.ts","sourceRoot":"","sources":["../../../src/tools/x402-pay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAc1D,eAAO,MAAM,iBAAiB,EAAE,OAiD/B,CAAC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * shroud_x402_pay — one-shot HTTP 402 client.
4
+ *
5
+ * Fetches a URL; if the server responds 402, the SDK signs an EIP-3009
6
+ * USDC transferWithAuthorization and retries automatically. Returns the
7
+ * server's final status, the body (if JSON-decodable), and the settled
8
+ * tx hash exposed via X-PAYMENT-RESPONSE when present.
9
+ *
10
+ * `maxPriceUsdcAtomic` is a hard safety cap. If the server demands more,
11
+ * the SDK throws X402AmountMismatchError without signing.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.shroudX402PayTool = void 0;
15
+ const zod_1 = require("zod");
16
+ const x402_1 = require("@shroud-fi/x402");
17
+ const errors_js_1 = require("../errors.js");
18
+ const schema_js_1 = require("./schema.js");
19
+ const ArgsSchema = zod_1.z
20
+ .object({
21
+ url: zod_1.z.string().url(),
22
+ method: zod_1.z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional(),
23
+ body: zod_1.z.string().optional(),
24
+ headers: zod_1.z.record(zod_1.z.string()).optional(),
25
+ maxPriceUsdcAtomic: schema_js_1.Uint256StringSchema.optional(),
26
+ })
27
+ .strict();
28
+ exports.shroudX402PayTool = {
29
+ name: 'shroud_x402_pay',
30
+ description: 'Fetch an HTTP URL. If the server responds 402, the SDK auto-signs EIP-3009 USDC payment using the agent operator wallet and retries. Returns final status, response body (if any), and settled tx hash (if X-PAYMENT-RESPONSE was returned). `maxPriceUsdcAtomic` caps how much the client will pay (base units, 6 decimals).',
31
+ inputSchema: {
32
+ type: 'object',
33
+ additionalProperties: false,
34
+ properties: {
35
+ url: { type: 'string' },
36
+ method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },
37
+ body: { type: 'string' },
38
+ headers: { type: 'object', additionalProperties: { type: 'string' } },
39
+ maxPriceUsdcAtomic: { type: 'string', pattern: '^\\d+$' },
40
+ },
41
+ required: ['url'],
42
+ },
43
+ async handler(ctx, raw) {
44
+ const parsed = ArgsSchema.safeParse(raw);
45
+ if (!parsed.success) {
46
+ throw new errors_js_1.McpInvalidArgsError();
47
+ }
48
+ const { url, method, body, headers, maxPriceUsdcAtomic } = parsed.data;
49
+ const client = (0, x402_1.createX402Client)({ transport: ctx.transport });
50
+ const init = {
51
+ method: method ?? 'GET',
52
+ ...(headers !== undefined ? { headers } : {}),
53
+ ...(body !== undefined ? { body } : {}),
54
+ ...(maxPriceUsdcAtomic !== undefined
55
+ ? { maxPriceAtomic: (0, schema_js_1.toBigInt)(maxPriceUsdcAtomic) }
56
+ : {}),
57
+ };
58
+ const response = await client.fetch(url, init);
59
+ const text = await response.text();
60
+ let json;
61
+ try {
62
+ json = JSON.parse(text);
63
+ }
64
+ catch {
65
+ json = null;
66
+ }
67
+ return {
68
+ ok: response.ok,
69
+ status: response.status,
70
+ bodyText: text.length > 4096 ? text.slice(0, 4096) : text,
71
+ bodyJson: json,
72
+ ...(response.x402Settlement !== undefined
73
+ ? { settledTxHash: response.x402Settlement.txHash }
74
+ : {}),
75
+ };
76
+ },
77
+ };
78
+ //# sourceMappingURL=x402-pay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402-pay.js","sourceRoot":"","sources":["../../../src/tools/x402-pay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * shroud_x402_serve — server-side x402 primitives.
3
+ *
4
+ * One tool, two ops:
5
+ * - op: 'challenge' → mint a 402 challenge bundle (headers + body) the
6
+ * caller serves from their own HTTP framework. Each challenge derives a
7
+ * FRESH stealth payTo address.
8
+ * - op: 'verify' → verify a client's signed X-PAYMENT payload against a
9
+ * prior challenge. Skip-facilitator mode by default — caller settles
10
+ * the EIP-3009 authorization on-chain themselves.
11
+ *
12
+ * Caller is responsible for transport (Express/Fastify/Next/etc) — this
13
+ * stays framework-agnostic.
14
+ */
15
+ import type { McpTool } from '../types.js';
16
+ export declare const shroudX402ServeTool: McpTool;
17
+ //# sourceMappingURL=x402-serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402-serve.d.ts","sourceRoot":"","sources":["../../../src/tools/x402-serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AA+B1D,eAAO,MAAM,mBAAmB,EAAE,OA4FjC,CAAC"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ /**
3
+ * shroud_x402_serve — server-side x402 primitives.
4
+ *
5
+ * One tool, two ops:
6
+ * - op: 'challenge' → mint a 402 challenge bundle (headers + body) the
7
+ * caller serves from their own HTTP framework. Each challenge derives a
8
+ * FRESH stealth payTo address.
9
+ * - op: 'verify' → verify a client's signed X-PAYMENT payload against a
10
+ * prior challenge. Skip-facilitator mode by default — caller settles
11
+ * the EIP-3009 authorization on-chain themselves.
12
+ *
13
+ * Caller is responsible for transport (Express/Fastify/Next/etc) — this
14
+ * stays framework-agnostic.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.shroudX402ServeTool = void 0;
18
+ const zod_1 = require("zod");
19
+ const x402_1 = require("@shroud-fi/x402");
20
+ const transport_1 = require("@shroud-fi/transport");
21
+ const errors_js_1 = require("../errors.js");
22
+ const schema_js_1 = require("./schema.js");
23
+ const ChallengeArgs = zod_1.z
24
+ .object({
25
+ op: zod_1.z.literal('challenge'),
26
+ resource: zod_1.z.string().min(1),
27
+ description: zod_1.z.string().optional(),
28
+ priceUsdcAtomic: schema_js_1.Uint256StringSchema.optional(),
29
+ })
30
+ .strict();
31
+ const VerifyArgs = zod_1.z
32
+ .object({
33
+ op: zod_1.z.literal('verify'),
34
+ signedPayloadBase64: zod_1.z.string().min(1),
35
+ challenge: zod_1.z.object({
36
+ body: zod_1.z.object({
37
+ x402Version: zod_1.z.literal(2),
38
+ error: zod_1.z.string(),
39
+ accepts: zod_1.z.array(zod_1.z.any()),
40
+ }),
41
+ headers: zod_1.z.record(zod_1.z.string()),
42
+ }),
43
+ skipFacilitator: zod_1.z.boolean().optional(),
44
+ })
45
+ .strict();
46
+ const ArgsSchema = zod_1.z.discriminatedUnion('op', [ChallengeArgs, VerifyArgs]);
47
+ exports.shroudX402ServeTool = {
48
+ name: 'shroud_x402_serve',
49
+ description: 'Server-side x402 primitives. `op: "challenge"` mints a fresh 402 challenge (headers + body + per-call stealth payTo); caller attaches to their HTTP response. `op: "verify"` verifies a client X-PAYMENT payload against a prior challenge. Defaults to skip-facilitator mode (caller settles on-chain themselves).',
50
+ inputSchema: {
51
+ type: 'object',
52
+ oneOf: [
53
+ {
54
+ properties: {
55
+ op: { const: 'challenge' },
56
+ resource: { type: 'string' },
57
+ description: { type: 'string' },
58
+ priceUsdcAtomic: { type: 'string', pattern: '^\\d+$' },
59
+ },
60
+ required: ['op', 'resource'],
61
+ },
62
+ {
63
+ properties: {
64
+ op: { const: 'verify' },
65
+ signedPayloadBase64: { type: 'string' },
66
+ challenge: { type: 'object' },
67
+ skipFacilitator: { type: 'boolean' },
68
+ },
69
+ required: ['op', 'signedPayloadBase64', 'challenge'],
70
+ },
71
+ ],
72
+ },
73
+ async handler(ctx, raw) {
74
+ const parsed = ArgsSchema.safeParse(raw);
75
+ if (!parsed.success) {
76
+ throw new errors_js_1.McpInvalidArgsError();
77
+ }
78
+ const usdc = (0, transport_1.getUSDC)(ctx.chainId);
79
+ if (usdc === undefined) {
80
+ throw new errors_js_1.McpInvalidArgsError();
81
+ }
82
+ const server = (0, x402_1.createX402Server)({
83
+ transport: ctx.transport,
84
+ chainId: ctx.chainId,
85
+ recipientMetaAddress: ctx.agent.metaAddressEncoded,
86
+ asset: usdc,
87
+ defaultPriceAtomic: parsed.data.op === 'challenge' && parsed.data.priceUsdcAtomic !== undefined
88
+ ? BigInt(parsed.data.priceUsdcAtomic)
89
+ : 10000n,
90
+ });
91
+ if (parsed.data.op === 'challenge') {
92
+ const args = {
93
+ resource: parsed.data.resource,
94
+ };
95
+ if (parsed.data.description !== undefined)
96
+ args.description = parsed.data.description;
97
+ if (parsed.data.priceUsdcAtomic !== undefined) {
98
+ args.priceAtomic = BigInt(parsed.data.priceUsdcAtomic);
99
+ }
100
+ const ch = await server.challenge(args);
101
+ return {
102
+ ok: true,
103
+ status: ch.status,
104
+ headers: ch.headers,
105
+ body: ch.body,
106
+ announcement: ch.announcement,
107
+ };
108
+ }
109
+ // op === 'verify' — caller round-trips the same shape they received from
110
+ // the challenge op. Cast through unknown so the schema declaration stays
111
+ // permissive (zod already ran structural checks).
112
+ const verifyResult = await server.verify({
113
+ signedPayload: parsed.data.signedPayloadBase64,
114
+ challenge: parsed.data.challenge,
115
+ skipFacilitator: parsed.data.skipFacilitator ?? true,
116
+ });
117
+ if (verifyResult.valid) {
118
+ return {
119
+ ok: true,
120
+ valid: true,
121
+ ...(verifyResult.settledTxHash !== undefined
122
+ ? { settledTxHash: verifyResult.settledTxHash }
123
+ : {}),
124
+ };
125
+ }
126
+ return {
127
+ ok: true,
128
+ valid: false,
129
+ error: verifyResult.error,
130
+ };
131
+ },
132
+ };
133
+ //# sourceMappingURL=x402-serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402-serve.js","sourceRoot":"","sources":["../../../src/tools/x402-serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Public types for @shroud-fi/mcp-server.
3
+ */
4
+ import type { Hex } from 'viem';
5
+ import type { ShroudAgent } from '@shroud-fi/agent-runtime';
6
+ import type { ShroudFiTransport } from '@shroud-fi/transport';
7
+ /**
8
+ * Resolved server context — what every tool handler receives.
9
+ *
10
+ * Built once by createMcpServer/bootstrap and reused for every tool call.
11
+ * No mutable state lives here; the scanner cursor is owned by the agent.
12
+ */
13
+ export interface McpServerContext {
14
+ readonly agent: ShroudAgent;
15
+ readonly transport: ShroudFiTransport;
16
+ readonly chainId: number;
17
+ /** Resolution of the operator's signing wallet, when present. */
18
+ readonly walletAddress: `0x${string}` | undefined;
19
+ }
20
+ /** JSON-safe tool result shape. MCP wraps this in a `content` array. */
21
+ export interface McpToolResult {
22
+ readonly ok: boolean;
23
+ readonly [k: string]: unknown;
24
+ }
25
+ /**
26
+ * Minimal tool descriptor. We mirror the MCP SDK shape but stay decoupled so
27
+ * tests can exercise tools without spinning up the full MCP server.
28
+ */
29
+ export interface McpTool {
30
+ readonly name: string;
31
+ readonly description: string;
32
+ readonly inputSchema: object;
33
+ readonly handler: (ctx: McpServerContext, args: unknown) => Promise<McpToolResult>;
34
+ }
35
+ /**
36
+ * EIP-191 challenge record. The HTTP transport caches outstanding challenges
37
+ * keyed by client wallet address until they expire or are consumed.
38
+ */
39
+ export interface Eip191Challenge {
40
+ readonly wallet: `0x${string}`;
41
+ readonly nonce: Hex;
42
+ readonly issuedAtMs: number;
43
+ readonly expiresAtMs: number;
44
+ readonly message: string;
45
+ }
46
+ /** Resolved server bootstrap config. */
47
+ export interface McpServerBootstrapConfig {
48
+ readonly chainId: number;
49
+ readonly rpcUrl: string;
50
+ readonly privateKey: Hex | undefined;
51
+ readonly startBlock: bigint;
52
+ /**
53
+ * Optional 32-byte deterministic master seed. When supplied, the
54
+ * ShroudAgent's stealth meta-address derivation is identical across every
55
+ * process that loads this config — required for multi-surface deployments
56
+ * (MCP + REST + UI) to agree on the operator's recipient identity. When
57
+ * undefined, ShroudAgent generates a random seed per boot.
58
+ */
59
+ readonly masterSeed: Uint8Array | undefined;
60
+ /**
61
+ * If non-empty, the HTTP transport rejects every authenticated request
62
+ * whose recovered wallet is not in this set. Stdio transport ignores it.
63
+ */
64
+ readonly httpAllowedWallets: ReadonlySet<`0x${string}`>;
65
+ }
66
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,aAAa,EAAE,KAAK,MAAM,EAAE,GAAG,SAAS,CAAC;CACnD;AAED,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,CAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,KACV,OAAO,CAAC,aAAa,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wCAAwC;AACxC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,GAAG,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;CACzD"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Public types for @shroud-fi/mcp-server.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * EIP-191 challenge-response auth for the HTTP transport.
3
+ *
4
+ * Flow:
5
+ * 1. Client POSTs /auth/challenge with their wallet address.
6
+ * 2. Server returns a fresh nonce + a canonical message string.
7
+ * 3. Client signs message with personal_sign / signMessage (EIP-191).
8
+ * 4. Client sends every subsequent request with:
9
+ * X-Shroudfi-Wallet: <0x… EOA>
10
+ * X-Shroudfi-Nonce: <nonce returned at step 2>
11
+ * X-Shroudfi-Signature: <0x… hex sig>
12
+ * 5. Server recovers, checks address match + expiry + allow-list.
13
+ *
14
+ * The signature is single-shot — once verifyAndConsume returns true for a
15
+ * nonce, the cache entry is deleted, so the same signed challenge cannot be
16
+ * replayed.
17
+ *
18
+ * Privacy: signature bytes never appear in logs, error messages, or response
19
+ * bodies. Errors are short tags only.
20
+ */
21
+ import type { Hex } from 'viem';
22
+ import type { Eip191Challenge } from './types.js';
23
+ export interface AuthCache {
24
+ issue(wallet: `0x${string}`): Eip191Challenge;
25
+ verifyAndConsume(args: {
26
+ wallet: `0x${string}`;
27
+ nonce: Hex;
28
+ signature: Hex;
29
+ }): Promise<void>;
30
+ /** Test seam — drop expired entries. Called automatically on every op. */
31
+ prune(now?: number): void;
32
+ /** Returns the current size — test seam. */
33
+ size(): number;
34
+ }
35
+ declare function buildMessage(wallet: `0x${string}`, nonce: Hex, issuedAtMs: number): string;
36
+ export declare function createAuthCache(ttlMs?: number): AuthCache;
37
+ export declare const __auth_test__: {
38
+ buildMessage: typeof buildMessage;
39
+ };
40
+ export {};
41
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAOhC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,eAAe,CAAC;IAC9C,gBAAgB,CAAC,IAAI,EAAE;QACrB,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;QACtB,KAAK,EAAE,GAAG,CAAC;QACX,SAAS,EAAE,GAAG,CAAC;KAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,0EAA0E;IAC1E,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,IAAI,IAAI,MAAM,CAAC;CAChB;AAID,iBAAS,YAAY,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWnF;AAED,wBAAgB,eAAe,CAC7B,KAAK,GAAE,MAAgC,GACtC,SAAS,CAgEX;AAED,eAAO,MAAM,aAAa;;CAAmB,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * EIP-191 challenge-response auth for the HTTP transport.
3
+ *
4
+ * Flow:
5
+ * 1. Client POSTs /auth/challenge with their wallet address.
6
+ * 2. Server returns a fresh nonce + a canonical message string.
7
+ * 3. Client signs message with personal_sign / signMessage (EIP-191).
8
+ * 4. Client sends every subsequent request with:
9
+ * X-Shroudfi-Wallet: <0x… EOA>
10
+ * X-Shroudfi-Nonce: <nonce returned at step 2>
11
+ * X-Shroudfi-Signature: <0x… hex sig>
12
+ * 5. Server recovers, checks address match + expiry + allow-list.
13
+ *
14
+ * The signature is single-shot — once verifyAndConsume returns true for a
15
+ * nonce, the cache entry is deleted, so the same signed challenge cannot be
16
+ * replayed.
17
+ *
18
+ * Privacy: signature bytes never appear in logs, error messages, or response
19
+ * bodies. Errors are short tags only.
20
+ */
21
+ import { randomBytes } from 'node:crypto';
22
+ import { recoverMessageAddress } from 'viem';
23
+ import { EIP191_CHALLENGE_TTL_MS } from './constants.js';
24
+ import { McpEip191ChallengeExpiredError, McpEip191SignatureInvalidError, McpUnauthorizedError, } from './errors.js';
25
+ const SHROUDFI_DOMAIN_MARK = 'ShroudFi MCP HTTP authentication';
26
+ function buildMessage(wallet, nonce, issuedAtMs) {
27
+ // The message is deliberately self-describing so a wallet UI shows the
28
+ // user the exact intent before signing. The nonce is the only random
29
+ // piece — it ties the signature to a single server-issued challenge.
30
+ return [
31
+ SHROUDFI_DOMAIN_MARK,
32
+ `Wallet: ${wallet}`,
33
+ `Nonce: ${nonce}`,
34
+ `Issued: ${new Date(issuedAtMs).toISOString()}`,
35
+ 'Sign to prove control of this wallet.',
36
+ ].join('\n');
37
+ }
38
+ export function createAuthCache(ttlMs = EIP191_CHALLENGE_TTL_MS) {
39
+ const store = new Map();
40
+ function makeKey(wallet, nonce) {
41
+ return `${wallet.toLowerCase()}|${nonce.toLowerCase()}`;
42
+ }
43
+ function prune(now = Date.now()) {
44
+ for (const [k, v] of store) {
45
+ if (v.expiresAtMs <= now)
46
+ store.delete(k);
47
+ }
48
+ }
49
+ return {
50
+ issue(wallet) {
51
+ prune();
52
+ const nonceBytes = randomBytes(16);
53
+ const nonce = `0x${nonceBytes.toString('hex')}`;
54
+ const now = Date.now();
55
+ const ch = {
56
+ wallet: wallet.toLowerCase(),
57
+ nonce,
58
+ issuedAtMs: now,
59
+ expiresAtMs: now + ttlMs,
60
+ message: buildMessage(wallet.toLowerCase(), nonce, now),
61
+ };
62
+ store.set(makeKey(ch.wallet, ch.nonce), ch);
63
+ return ch;
64
+ },
65
+ async verifyAndConsume({ wallet, nonce, signature }) {
66
+ // Don't prune before lookup — we want callers to see the explicit
67
+ // `auth_challenge_expired` code when their nonce has timed out, instead
68
+ // of an indistinguishable `unauthorized`.
69
+ const key = makeKey(wallet, nonce);
70
+ const ch = store.get(key);
71
+ if (ch === undefined) {
72
+ throw new McpUnauthorizedError();
73
+ }
74
+ if (ch.expiresAtMs <= Date.now()) {
75
+ store.delete(key);
76
+ throw new McpEip191ChallengeExpiredError();
77
+ }
78
+ let recovered;
79
+ try {
80
+ recovered = await recoverMessageAddress({
81
+ message: ch.message,
82
+ signature,
83
+ });
84
+ }
85
+ catch {
86
+ throw new McpEip191SignatureInvalidError();
87
+ }
88
+ if (recovered.toLowerCase() !== ch.wallet.toLowerCase()) {
89
+ throw new McpEip191SignatureInvalidError();
90
+ }
91
+ // Single-use: consume the nonce so the signed challenge can't be replayed.
92
+ store.delete(key);
93
+ },
94
+ prune,
95
+ size: () => store.size,
96
+ };
97
+ }
98
+ export const __auth_test__ = { buildMessage };
99
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HTTP transport bin. Reads SHROUDFI_MCP_HTTP_PORT (default 7070) via the
4
+ * config module, boots the HTTP server, parks until SIGINT/SIGTERM.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/bin/http.ts"],"names":[],"mappings":";AACA;;;GAGG"}