@x402scan/mcp 0.0.7-beta.4 → 0.0.7

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/dist/esm/index.js CHANGED
@@ -1,9 +1,2654 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-Q2QVXJFE.js";
2
+ import z$1, { z } from 'zod';
3
+ import { getAddress, formatUnits } from 'viem';
4
+ import path2, { join } from 'path';
5
+ import os, { homedir } from 'os';
6
+ import * as fs from 'fs';
7
+ import fs__default, { appendFileSync } from 'fs';
8
+ import { polygon, arbitrum, optimism, sepolia, mainnet, baseSepolia, base } from 'viem/chains';
9
+ import { intro, outro, log as log$1, confirm, stream, spinner, select, text } from '@clack/prompts';
10
+ import { errAsync, ResultAsync, err } from 'neverthrow';
11
+ import chalk from 'chalk';
12
+ import open from 'open';
13
+ import { x402HTTPClient, x402Client } from '@x402/core/client';
14
+ import { ExactEvmScheme } from '@x402/evm/exact/client';
15
+ import { wrapFetchWithPayment } from '@x402/fetch';
16
+ import { base58 } from '@scure/base';
17
+ import 'tweetnacl';
18
+ import { SiweMessage } from 'siwe';
19
+ import { safeBase64Encode } from '@x402/core/utils';
20
+ import 'url';
21
+ import { randomBytes } from 'crypto';
22
+ import * as fs3 from 'fs/promises';
23
+ import { privateKeyToAccount } from 'viem/accounts';
24
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
25
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
26
+ import process2 from 'process';
27
+ import * as TOML from '@iarna/toml';
28
+ import yaml from 'js-yaml';
29
+ import * as jsonc from 'jsonc-parser';
30
+ import yargs from 'yargs';
31
+ import { hideBin } from 'yargs/helpers';
32
+
33
+ var __defProp = Object.defineProperty;
34
+ var __getOwnPropNames = Object.getOwnPropertyNames;
35
+ var __esm = (fn, res) => function __init() {
36
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
37
+ };
38
+ var __export = (target, all) => {
39
+ for (var name in all)
40
+ __defProp(target, name, { get: all[name], enumerable: true });
41
+ };
42
+
43
+ // src/install/clients.ts
44
+ var Clients, clientMetadata;
45
+ var init_clients = __esm({
46
+ "src/install/clients.ts"() {
47
+ Clients = /* @__PURE__ */ ((Clients2) => {
48
+ Clients2["ClaudeCode"] = "claude-code";
49
+ Clients2["Cursor"] = "cursor";
50
+ Clients2["Claude"] = "claude";
51
+ Clients2["Codex"] = "codex";
52
+ Clients2["Vscode"] = "vscode";
53
+ Clients2["Cline"] = "cline";
54
+ Clients2["RooCline"] = "roo-cline";
55
+ Clients2["Windsurf"] = "windsurf";
56
+ Clients2["Warp"] = "warp";
57
+ Clients2["GeminiCli"] = "gemini-cli";
58
+ Clients2["Goose"] = "goose";
59
+ Clients2["Zed"] = "zed";
60
+ Clients2["Opencode"] = "opencode";
61
+ return Clients2;
62
+ })(Clients || {});
63
+ clientMetadata = {
64
+ ["claude-code" /* ClaudeCode */]: {
65
+ name: "Claude Code",
66
+ description: "Claude Code is a code editor that uses the Claude API.",
67
+ website: "https://claude.com"
68
+ },
69
+ ["cursor" /* Cursor */]: {
70
+ name: "Cursor",
71
+ description: "Cursor is a code editor that uses the Cursor API.",
72
+ website: "https://cursor.com"
73
+ },
74
+ ["claude" /* Claude */]: {
75
+ name: "Claude Desktop",
76
+ description: "Claude is a code editor that uses the Claude API.",
77
+ website: "https://claude.com"
78
+ },
79
+ ["codex" /* Codex */]: {
80
+ name: "Codex",
81
+ description: "Codex is a code editor that uses the Codex API.",
82
+ website: "https://codex.com"
83
+ },
84
+ ["vscode" /* Vscode */]: {
85
+ name: "VSCode",
86
+ description: "VSCode is a code editor that uses the VSCode API.",
87
+ website: "https://vscode.com"
88
+ },
89
+ ["cline" /* Cline */]: {
90
+ name: "Cline",
91
+ description: "Cline is a code editor that uses the Cline API.",
92
+ website: "https://cline.com"
93
+ },
94
+ ["roo-cline" /* RooCline */]: {
95
+ name: "RooCline",
96
+ description: "RooCline is a code editor that uses the RooCline API.",
97
+ website: "https://roo-cline.com"
98
+ },
99
+ ["windsurf" /* Windsurf */]: {
100
+ name: "Windsurf",
101
+ description: "Windsurf is a code editor that uses the Windsurf API.",
102
+ website: "https://windsurf.com"
103
+ },
104
+ ["warp" /* Warp */]: {
105
+ name: "Warp",
106
+ description: "Warp is a code editor that uses the Warp API.",
107
+ website: "https://warp.com"
108
+ },
109
+ ["gemini-cli" /* GeminiCli */]: {
110
+ name: "Gemini CLI",
111
+ description: "Gemini CLI is a code editor that uses the Gemini CLI API.",
112
+ website: "https://gemini-cli.com"
113
+ },
114
+ ["goose" /* Goose */]: {
115
+ name: "Goose",
116
+ description: "Goose is a code editor that uses the Goose API.",
117
+ website: "https://goose.com"
118
+ },
119
+ ["zed" /* Zed */]: {
120
+ name: "Zed",
121
+ description: "Zed is a code editor that uses the Zed API.",
122
+ website: "https://zed.com"
123
+ },
124
+ ["opencode" /* Opencode */]: {
125
+ name: "Opencode",
126
+ description: "Opencode is a code editor that uses the Opencode API.",
127
+ website: "https://opencode.com"
128
+ }
129
+ };
130
+ }
131
+ });
132
+
133
+ // src/server/lib/response.ts
134
+ var mcpSuccess, mcpError;
135
+ var init_response = __esm({
136
+ "src/server/lib/response.ts"() {
137
+ mcpSuccess = (data) => {
138
+ return {
139
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
140
+ };
141
+ };
142
+ mcpError = (error, context) => {
143
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
144
+ const details = error instanceof Error && error.cause ? { cause: JSON.stringify(error.cause) } : void 0;
145
+ return {
146
+ content: [
147
+ {
148
+ type: "text",
149
+ text: JSON.stringify(
150
+ {
151
+ error: message,
152
+ ...details && { details },
153
+ ...context && { context }
154
+ },
155
+ null,
156
+ 2
157
+ )
158
+ }
159
+ ],
160
+ isError: true
161
+ };
162
+ };
163
+ }
164
+ });
165
+ var ethereumAddressSchema, ethereumPrivateKeySchema, requestSchema, requestWithHeadersSchema;
166
+ var init_schemas = __esm({
167
+ "src/server/lib/schemas.ts"() {
168
+ ethereumAddressSchema = z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address").transform((address) => getAddress(address));
169
+ ethereumPrivateKeySchema = z$1.string().regex(/^0x[a-fA-F0-9]{64}$/, "Invalid Ethereum private key").transform((privateKey) => privateKey);
170
+ requestSchema = z$1.object({
171
+ url: z$1.url().describe("The endpoint URL"),
172
+ method: z$1.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).default("GET").describe("HTTP method"),
173
+ body: z$1.unknown().optional().describe("Request body for POST/PUT/PATCH methods")
174
+ });
175
+ requestWithHeadersSchema = requestSchema.extend({
176
+ headers: z$1.record(z$1.string(), z$1.string()).optional().describe("Additional headers to include").default({})
177
+ });
178
+ }
179
+ });
180
+
181
+ // src/server/types.ts
182
+ var init_types = __esm({
183
+ "src/server/types.ts"() {
184
+ }
185
+ });
186
+ var BASE_DIRECTORY, configFile;
187
+ var init_fs = __esm({
188
+ "src/lib/fs.ts"() {
189
+ BASE_DIRECTORY = join(homedir(), ".x402scan-mcp");
190
+ if (!fs.existsSync(BASE_DIRECTORY)) {
191
+ fs.mkdirSync(BASE_DIRECTORY, { recursive: true });
192
+ }
193
+ configFile = (name) => {
194
+ if (!fs.existsSync(BASE_DIRECTORY)) {
195
+ fs.mkdirSync(BASE_DIRECTORY, { recursive: true });
196
+ }
197
+ const filePath = join(BASE_DIRECTORY, name);
198
+ if (!fs.existsSync(filePath)) {
199
+ fs.writeFileSync(filePath, "{}");
200
+ }
201
+ return filePath;
202
+ };
203
+ }
204
+ });
205
+ function format(args) {
206
+ return args.map(
207
+ (a) => typeof a === "object" && a !== null ? JSON.stringify(a) : String(a)
208
+ ).join(" ");
209
+ }
210
+ function write(level, msg, args) {
211
+ const formatted = args.length ? `${msg} ${format(args)}` : msg;
212
+ const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${formatted}
213
+ `;
214
+ try {
215
+ appendFileSync(LOG_FILE, line);
216
+ } catch {
217
+ }
218
+ if (process.env.X402_DEBUG === "true") {
219
+ console.error(`[x402scan] ${formatted}`);
220
+ }
221
+ }
222
+ var LOG_FILE, DEBUG, log;
223
+ var init_log = __esm({
224
+ "src/lib/log.ts"() {
225
+ init_fs();
226
+ LOG_FILE = configFile("mcp.log");
227
+ DEBUG = process.env.X402_DEBUG === "true";
228
+ log = {
229
+ info: (msg, ...args) => write("INFO", msg, args),
230
+ error: (msg, ...args) => write("ERROR", msg, args),
231
+ debug: (msg, ...args) => DEBUG && write("DEBUG", msg, args),
232
+ path: LOG_FILE
233
+ };
234
+ }
235
+ });
236
+ function toCaip2(network) {
237
+ if (network.startsWith("eip155:")) return network;
238
+ return V1_TO_CAIP2[network.toLowerCase()] ?? network;
239
+ }
240
+ function getChainConfig(network) {
241
+ return CHAIN_CONFIGS[toCaip2(network)];
242
+ }
243
+ function getChainName(network) {
244
+ return getChainConfig(network)?.chain.name ?? network;
245
+ }
246
+ var CHAIN_CONFIGS, V1_TO_CAIP2, DEFAULT_NETWORK;
247
+ var init_networks = __esm({
248
+ "src/lib/networks.ts"() {
249
+ CHAIN_CONFIGS = {
250
+ "eip155:8453": {
251
+ chain: base,
252
+ caip2: "eip155:8453",
253
+ v1Name: "base",
254
+ usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
255
+ },
256
+ "eip155:84532": {
257
+ chain: baseSepolia,
258
+ caip2: "eip155:84532",
259
+ v1Name: "base-sepolia",
260
+ usdcAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
261
+ },
262
+ "eip155:1": {
263
+ chain: mainnet,
264
+ caip2: "eip155:1",
265
+ v1Name: "ethereum",
266
+ usdcAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
267
+ },
268
+ "eip155:11155111": {
269
+ chain: sepolia,
270
+ caip2: "eip155:11155111",
271
+ v1Name: "ethereum-sepolia",
272
+ usdcAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
273
+ },
274
+ "eip155:10": {
275
+ chain: optimism,
276
+ caip2: "eip155:10",
277
+ v1Name: "optimism",
278
+ usdcAddress: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"
279
+ },
280
+ "eip155:42161": {
281
+ chain: arbitrum,
282
+ caip2: "eip155:42161",
283
+ v1Name: "arbitrum",
284
+ usdcAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
285
+ },
286
+ "eip155:137": {
287
+ chain: polygon,
288
+ caip2: "eip155:137",
289
+ v1Name: "polygon",
290
+ usdcAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
291
+ }
292
+ };
293
+ V1_TO_CAIP2 = {
294
+ base: "eip155:8453",
295
+ "base-sepolia": "eip155:84532",
296
+ ethereum: "eip155:1",
297
+ "ethereum-sepolia": "eip155:11155111",
298
+ optimism: "eip155:10",
299
+ arbitrum: "eip155:42161",
300
+ polygon: "eip155:137"
301
+ };
302
+ DEFAULT_NETWORK = "eip155:8453";
303
+ }
304
+ });
305
+ var tokenStringToNumber;
306
+ var init_token = __esm({
307
+ "src/lib/token.ts"() {
308
+ tokenStringToNumber = (amount, decimals = 6) => {
309
+ return Number(formatUnits(BigInt(amount), decimals));
310
+ };
311
+ }
312
+ });
313
+
314
+ // src/lib/utils.ts
315
+ var getBaseUrl;
316
+ var init_utils = __esm({
317
+ "src/lib/utils.ts"() {
318
+ getBaseUrl = (dev) => {
319
+ return dev ? "http://localhost:3000" : "https://x402scan.com";
320
+ };
321
+ }
322
+ });
323
+ async function getUSDCBalance(address, flags) {
324
+ const url = `${getBaseUrl(flags.dev)}/api/rpc/balance/${address}`;
325
+ const res = await fetch(url, {
326
+ method: "GET",
327
+ headers: {
328
+ accept: "application/json"
329
+ }
330
+ });
331
+ if (!res.ok) {
332
+ throw new Error(
333
+ `Balance API request failed (${res.status} ${res.statusText})`
334
+ );
335
+ }
336
+ let json;
337
+ try {
338
+ json = await res.json();
339
+ } catch {
340
+ throw new Error(
341
+ `Failed to parse balance API response as JSON (${res.status} ${res.statusText})`
342
+ );
343
+ }
344
+ const result = balanceApiResponseSchema.safeParse(json);
345
+ if (!result.success) {
346
+ throw new Error(
347
+ `Failed to safeParse balance API response (${res.status} ${res.statusText})`
348
+ );
349
+ }
350
+ return {
351
+ balanceFormatted: result.data.balance,
352
+ balanceRaw: result.data.rawBalance
353
+ };
354
+ }
355
+ var balanceApiResponseSchema;
356
+ var init_balance = __esm({
357
+ "src/lib/balance.ts"() {
358
+ init_utils();
359
+ balanceApiResponseSchema = z.object({
360
+ address: z.string(),
361
+ chain: z.number().int(),
362
+ balance: z.coerce.number(),
363
+ rawBalance: z.string()
364
+ });
365
+ }
366
+ });
367
+ var wait;
368
+ var init_wait = __esm({
369
+ "src/lib/wait.ts"() {
370
+ wait = async ({ startText, stopText, ms }) => {
371
+ const { start: startSpinner, stop: stopSpinner } = spinner();
372
+ startSpinner(startText);
373
+ await new Promise((resolve) => setTimeout(resolve, ms));
374
+ stopSpinner(stopText);
375
+ };
376
+ }
377
+ });
378
+ function safeFetch(input, init) {
379
+ return ResultAsync.fromPromise(
380
+ fetch(input, init),
381
+ (error) => ({
382
+ type: "network",
383
+ message: "Network error",
384
+ error: error instanceof Error ? error : new Error(String(error))
385
+ })
386
+ );
387
+ }
388
+ var safeFetchJson;
389
+ var init_safe_fetch = __esm({
390
+ "src/lib/safe-fetch.ts"() {
391
+ safeFetchJson = (input, init, errorMessage) => {
392
+ return safeFetch(input, init).andThen((response) => {
393
+ if (!response.ok) {
394
+ return ResultAsync.fromSafePromise(
395
+ response.json().catch(() => void 0)
396
+ ).andThen(
397
+ (json) => err({
398
+ type: "http",
399
+ message: json !== void 0 && errorMessage ? errorMessage(json) : response.statusText,
400
+ status: response.status,
401
+ headers: response.headers,
402
+ json
403
+ })
404
+ );
405
+ }
406
+ return ResultAsync.fromPromise(
407
+ response.json(),
408
+ (error) => ({
409
+ type: "parse",
410
+ message: "Could not parse JSON from response",
411
+ error: error instanceof Error ? error : new Error(String(error))
412
+ })
413
+ );
414
+ });
415
+ };
416
+ }
417
+ });
418
+ var STATE_FILE, stateSchema, getState, setState;
419
+ var init_state = __esm({
420
+ "src/lib/state.ts"() {
421
+ init_fs();
422
+ init_log();
423
+ STATE_FILE = configFile("state.json");
424
+ stateSchema = z$1.looseObject({
425
+ redeemedCodes: z$1.array(z$1.string())
426
+ }).partial();
427
+ getState = () => {
428
+ if (!fs__default.existsSync(STATE_FILE)) {
429
+ fs__default.writeFileSync(STATE_FILE, JSON.stringify({}));
430
+ return {};
431
+ }
432
+ const result = stateSchema.safeParse(
433
+ JSON.parse(fs__default.readFileSync(STATE_FILE, "utf-8"))
434
+ );
435
+ if (!result.success) {
436
+ log.error("Failed to parse state", { error: result.error });
437
+ return {};
438
+ }
439
+ return result.data;
440
+ };
441
+ setState = (state) => {
442
+ const existing = getState();
443
+ const newState = stateSchema.parse({ ...existing, ...state });
444
+ fs__default.writeFileSync(STATE_FILE, JSON.stringify(newState, null, 2));
445
+ };
446
+ }
447
+ });
448
+ var redeemInviteCode;
449
+ var init_redeem_invite = __esm({
450
+ "src/lib/redeem-invite.ts"() {
451
+ init_safe_fetch();
452
+ init_utils();
453
+ init_state();
454
+ redeemInviteCode = async ({
455
+ code,
456
+ dev,
457
+ address
458
+ }) => {
459
+ const state = getState();
460
+ if (state.redeemedCodes?.includes(code)) {
461
+ return Promise.resolve(
462
+ errAsync({
463
+ success: false,
464
+ message: "This invite code has already been redeemed"
465
+ })
466
+ );
467
+ }
468
+ return await safeFetchJson(
469
+ `${getBaseUrl(dev)}/api/invite/redeem`,
470
+ {
471
+ method: "POST",
472
+ headers: {
473
+ "Content-Type": "application/json"
474
+ },
475
+ body: JSON.stringify({
476
+ code,
477
+ recipientAddr: address
478
+ })
479
+ },
480
+ ({ message }) => message
481
+ ).andTee((result) => {
482
+ if (result.success) {
483
+ setState({
484
+ redeemedCodes: [...state.redeemedCodes ?? [], code]
485
+ });
486
+ }
487
+ });
488
+ };
489
+ }
490
+ });
491
+ var getDepositLink, openDepositLink, redeemInviteCodePrompt, promptDeposit;
492
+ var init_deposit = __esm({
493
+ "src/lib/deposit.ts"() {
494
+ init_networks();
495
+ init_wait();
496
+ init_redeem_invite();
497
+ init_utils();
498
+ getDepositLink = (address, flags) => {
499
+ return `${getBaseUrl(flags.dev)}/mcp/deposit/${address}`;
500
+ };
501
+ openDepositLink = async (address, flags) => {
502
+ const depositLink = getDepositLink(address, flags);
503
+ await open(depositLink);
504
+ };
505
+ redeemInviteCodePrompt = async (address, flags) => {
506
+ const code = await text({
507
+ message: "Enter your invite code",
508
+ placeholder: "MRT-XXXXX",
509
+ validate: (value) => {
510
+ if (!value || value.trim().length === 0) {
511
+ return "Please enter an invite code";
512
+ }
513
+ }
514
+ });
515
+ if (typeof code !== "string") {
516
+ return false;
517
+ }
518
+ const s = spinner();
519
+ s.start("Redeeming invite code...");
520
+ const result = await redeemInviteCode({ code, dev: flags.dev, address });
521
+ return result.match(
522
+ async ({ data: { amount, txHash } }) => {
523
+ s.stop("Invite code redeemed successfully!");
524
+ await wait({
525
+ startText: "Processing...",
526
+ stopText: chalk.green(
527
+ `${chalk.bold(amount)} USDC has been sent to your wallet!`
528
+ ),
529
+ ms: 1500
530
+ });
531
+ log$1.success(
532
+ chalk.bold(`Your wallet has been funded with ${amount} USDC`)
533
+ );
534
+ if (txHash) {
535
+ log$1.info(chalk.dim(`Transaction: https://basescan.org/tx/${txHash}`));
536
+ }
537
+ return true;
538
+ },
539
+ (error) => {
540
+ s.stop("Invite code redemption failed");
541
+ log$1.warning(
542
+ chalk.yellow(`Failed to redeem invite code: ${error?.message}`)
543
+ );
544
+ return false;
545
+ }
546
+ );
547
+ };
548
+ promptDeposit = async (address, flags) => {
549
+ const depositLink = getDepositLink(address, flags);
550
+ const depositChoice = flags.yes ? "manual" : await select({
551
+ message: chalk.bold("How would you like to deposit?"),
552
+ initialValue: "guided",
553
+ options: [
554
+ {
555
+ label: "Guided - Recommended",
556
+ value: "guided",
557
+ hint: "Online portal in x402scan"
558
+ },
559
+ {
560
+ label: "Manual",
561
+ value: "manual",
562
+ hint: "Print deposit instructions"
563
+ },
564
+ {
565
+ label: "Redeem Invite Code",
566
+ value: "invite",
567
+ hint: "Enter an invite code for starter money"
568
+ },
569
+ {
570
+ label: "Skip",
571
+ value: void 0,
572
+ hint: "Skip deposit process - functionality limited"
573
+ }
574
+ ]
575
+ });
576
+ if (depositChoice === "guided") {
577
+ await wait({
578
+ startText: "Opening deposit page...",
579
+ stopText: `Opening ${chalk.underline.hex("#2563eb")(depositLink)}`,
580
+ ms: 1e3
581
+ });
582
+ await open(depositLink);
583
+ } else if (depositChoice === "manual") {
584
+ log$1.step(chalk.bold("Account Information"));
585
+ log$1.message(`Address: ${address}`);
586
+ log$1.message(`Network: ${getChainName(DEFAULT_NETWORK)}`);
587
+ log$1.step(chalk.bold("Online Portal"));
588
+ log$1.message(`${chalk.underline(depositLink)}`);
589
+ } else if (depositChoice === "invite") {
590
+ const redeemed = await redeemInviteCodePrompt(address, flags);
591
+ if (!redeemed) {
592
+ await promptDeposit(address, flags);
593
+ }
594
+ }
595
+ };
596
+ }
597
+ });
598
+
599
+ // src/server/lib/check-balance.ts
600
+ var checkBalance;
601
+ var init_check_balance = __esm({
602
+ "src/server/lib/check-balance.ts"() {
603
+ init_balance();
604
+ init_deposit();
605
+ checkBalance = async ({
606
+ server,
607
+ address,
608
+ amountNeeded,
609
+ message,
610
+ flags
611
+ }) => {
612
+ const { balanceFormatted } = await getUSDCBalance(address, flags);
613
+ if (balanceFormatted < amountNeeded) {
614
+ const capabilities = server.server.getClientCapabilities();
615
+ if (!capabilities?.elicitation) {
616
+ throw new Error(
617
+ `${message(balanceFormatted)}
618
+
619
+ You can deposit USDC at ${getDepositLink(address, flags)}`
620
+ );
621
+ }
622
+ const result = await server.server.elicitInput({
623
+ mode: "form",
624
+ message: message(balanceFormatted),
625
+ requestedSchema: {
626
+ type: "object",
627
+ properties: {}
628
+ }
629
+ });
630
+ if (result.action === "accept") {
631
+ await openDepositLink(address, flags);
632
+ }
633
+ }
634
+ return balanceFormatted;
635
+ };
636
+ }
637
+ });
638
+
639
+ // src/server/lib/parse-response.ts
640
+ var parseResponse;
641
+ var init_parse_response = __esm({
642
+ "src/server/lib/parse-response.ts"() {
643
+ parseResponse = async (response) => {
644
+ try {
645
+ const contentType = response.headers.get("content-type") ?? "";
646
+ if (contentType.includes("application/json")) {
647
+ return await response.json();
648
+ } else if (contentType.includes("image/")) {
649
+ return await response.arrayBuffer();
650
+ } else {
651
+ return await response.text();
652
+ }
653
+ } catch {
654
+ return void 0;
655
+ }
656
+ };
657
+ }
658
+ });
659
+ var registerFetchX402ResourceTool;
660
+ var init_fetch_x402_resource = __esm({
661
+ "src/server/tools/fetch-x402-resource.ts"() {
662
+ init_response();
663
+ init_schemas();
664
+ init_types();
665
+ init_log();
666
+ init_networks();
667
+ init_token();
668
+ init_check_balance();
669
+ init_parse_response();
670
+ registerFetchX402ResourceTool = ({
671
+ server,
672
+ account,
673
+ flags,
674
+ sessionId
675
+ }) => {
676
+ server.registerTool(
677
+ "fetch",
678
+ {
679
+ description: "Fetches an x402-protected resource and handles payment automatically. If the resource is not x402-protected, it will return the raw response.",
680
+ inputSchema: requestWithHeadersSchema
681
+ },
682
+ async ({ url, method, body, headers }) => {
683
+ const coreClient = x402Client.fromConfig({
684
+ schemes: [
685
+ { network: DEFAULT_NETWORK, client: new ExactEvmScheme(account) }
686
+ ]
687
+ });
688
+ let state = "initial_request" /* INITIAL_REQUEST */;
689
+ coreClient.onBeforePaymentCreation(async ({ selectedRequirements }) => {
690
+ const amount = tokenStringToNumber(selectedRequirements.amount);
691
+ await checkBalance({
692
+ server,
693
+ address: account.address,
694
+ amountNeeded: amount,
695
+ message: (balance) => `This request costs ${amount} USDC. Your current balance is ${balance} USDC.`,
696
+ flags
697
+ });
698
+ state = "payment_required" /* PAYMENT_REQUIRED */;
699
+ });
700
+ coreClient.onAfterPaymentCreation(async (ctx) => {
701
+ state = "payment_created" /* PAYMENT_CREATED */;
702
+ log.info("After payment creation", ctx);
703
+ return Promise.resolve();
704
+ });
705
+ coreClient.onPaymentCreationFailure(async (ctx) => {
706
+ state = "payment_failed" /* PAYMENT_FAILED */;
707
+ log.info("Payment creation failure", ctx);
708
+ return Promise.resolve();
709
+ });
710
+ const client = new x402HTTPClient(coreClient);
711
+ const fetchWithPay = wrapFetchWithPayment(fetch, client);
712
+ try {
713
+ const response = await fetchWithPay(url, {
714
+ method,
715
+ body: typeof body === "string" ? body : body ? JSON.stringify(body) : void 0,
716
+ headers: {
717
+ ...body ? { "Content-Type": "application/json" } : {},
718
+ "X-Wallet-Address": account.address,
719
+ "X-Client-ID": account.address,
720
+ "X-Session-ID": sessionId,
721
+ ...headers
722
+ }
723
+ });
724
+ if (!response.ok) {
725
+ const errorResponse = {
726
+ data: await parseResponse(response),
727
+ statusCode: response.status,
728
+ state
729
+ };
730
+ if (response.status === 402) {
731
+ return mcpError("Payment required", errorResponse);
732
+ }
733
+ return mcpError(
734
+ response.statusText ?? "Request failed",
735
+ errorResponse
736
+ );
737
+ }
738
+ const getSettlement = () => {
739
+ try {
740
+ return client.getPaymentSettleResponse(
741
+ (name) => response.headers.get(name)
742
+ );
743
+ } catch {
744
+ return void 0;
745
+ }
746
+ };
747
+ const settlement = getSettlement();
748
+ return mcpSuccess({
749
+ data: await parseResponse(response),
750
+ payment: settlement
751
+ });
752
+ } catch (err2) {
753
+ return mcpError(err2, { state });
754
+ }
755
+ }
756
+ );
757
+ };
758
+ }
759
+ });
760
+
761
+ // src/server/lib/x402/protocol.ts
762
+ function isV1Response(pr) {
763
+ if (!pr || typeof pr !== "object") return false;
764
+ const obj = pr;
765
+ if (obj.x402Version === 1) return true;
766
+ const accepts = obj.accepts;
767
+ if (Array.isArray(accepts) && accepts.length > 0) {
768
+ return "maxAmountRequired" in accepts[0];
769
+ }
770
+ return false;
771
+ }
772
+ function normalizeV1Requirement(req) {
773
+ if (!req.maxAmountRequired) {
774
+ throw new Error("v1 requirement missing maxAmountRequired field");
775
+ }
776
+ return {
777
+ scheme: req.scheme,
778
+ network: req.network,
779
+ amount: req.maxAmountRequired,
780
+ asset: req.asset,
781
+ payTo: req.payTo,
782
+ maxTimeoutSeconds: req.maxTimeoutSeconds,
783
+ extra: req.extra,
784
+ resource: req.resource,
785
+ description: req.description,
786
+ mimeType: req.mimeType
787
+ };
788
+ }
789
+ function normalizeV2Requirement(req) {
790
+ if (!req.amount) {
791
+ throw new Error("v2 requirement missing amount field");
792
+ }
793
+ return {
794
+ scheme: req.scheme,
795
+ network: req.network,
796
+ amount: req.amount,
797
+ asset: req.asset,
798
+ payTo: req.payTo,
799
+ maxTimeoutSeconds: req.maxTimeoutSeconds,
800
+ extra: req.extra
801
+ };
802
+ }
803
+ function normalizePaymentRequired(pr) {
804
+ const version = pr.x402Version ?? 1;
805
+ if (isV1Response(pr)) {
806
+ const v1 = pr;
807
+ return {
808
+ x402Version: 1,
809
+ error: v1.error,
810
+ accepts: v1.accepts.map(normalizeV1Requirement)
811
+ };
812
+ }
813
+ const v2 = pr;
814
+ return {
815
+ x402Version: version,
816
+ error: v2.error,
817
+ accepts: v2.accepts.map(normalizeV2Requirement),
818
+ resource: v2.resource,
819
+ extensions: v2.extensions
820
+ };
821
+ }
822
+ var init_protocol = __esm({
823
+ "src/server/lib/x402/protocol.ts"() {
824
+ }
825
+ });
826
+ function extractSolanaChainReference(chainId) {
827
+ const [, reference] = chainId.split(":");
828
+ return reference;
829
+ }
830
+ function formatSIWSMessage(info, address) {
831
+ const lines = [
832
+ `${info.domain} wants you to sign in with your Solana account:`,
833
+ address,
834
+ ""
835
+ ];
836
+ if (info.statement) {
837
+ lines.push(info.statement, "");
838
+ }
839
+ lines.push(
840
+ `URI: ${info.uri}`,
841
+ `Version: ${info.version}`,
842
+ `Chain ID: ${extractSolanaChainReference(info.chainId)}`,
843
+ `Nonce: ${info.nonce}`,
844
+ `Issued At: ${info.issuedAt}`
845
+ );
846
+ if (info.expirationTime) {
847
+ lines.push(`Expiration Time: ${info.expirationTime}`);
848
+ }
849
+ if (info.notBefore) {
850
+ lines.push(`Not Before: ${info.notBefore}`);
851
+ }
852
+ if (info.requestId) {
853
+ lines.push(`Request ID: ${info.requestId}`);
854
+ }
855
+ if (info.resources && info.resources.length > 0) {
856
+ lines.push("Resources:");
857
+ for (const resource of info.resources) {
858
+ lines.push(`- ${resource}`);
859
+ }
860
+ }
861
+ return lines.join("\n");
862
+ }
863
+ function encodeBase58(bytes) {
864
+ return base58.encode(bytes);
865
+ }
866
+ var init_solana = __esm({
867
+ "src/server/vendor/sign-in-with-x/solana.ts"() {
868
+ }
869
+ });
870
+
871
+ // src/server/vendor/sign-in-with-x/sign.ts
872
+ function getEVMAddress(signer) {
873
+ if (signer.account?.address) {
874
+ return signer.account.address;
875
+ }
876
+ if (signer.address) {
877
+ return signer.address;
878
+ }
879
+ throw new Error("EVM signer missing address");
880
+ }
881
+ function getSolanaAddress(signer) {
882
+ const pk = signer.publicKey;
883
+ return typeof pk === "string" ? pk : pk.toBase58();
884
+ }
885
+ async function signEVMMessage(message, signer) {
886
+ if (signer.account) {
887
+ return signer.signMessage({ message, account: signer.account });
888
+ }
889
+ return signer.signMessage({ message });
890
+ }
891
+ async function signSolanaMessage(message, signer) {
892
+ const messageBytes = new TextEncoder().encode(message);
893
+ const signatureBytes = await signer.signMessage(messageBytes);
894
+ return encodeBase58(signatureBytes);
895
+ }
896
+ var init_sign = __esm({
897
+ "src/server/vendor/sign-in-with-x/sign.ts"() {
898
+ init_solana();
899
+ }
900
+ });
901
+ function extractEVMChainId(chainId) {
902
+ const match = /^eip155:(\d+)$/.exec(chainId);
903
+ if (!match) {
904
+ throw new Error(
905
+ `Invalid EVM chainId format: ${chainId}. Expected eip155:<number>`
906
+ );
907
+ }
908
+ return parseInt(match[1], 10);
909
+ }
910
+ function formatSIWEMessage(info, address) {
911
+ const numericChainId = extractEVMChainId(info.chainId);
912
+ const siweMessage = new SiweMessage({
913
+ domain: info.domain,
914
+ address,
915
+ statement: info.statement,
916
+ uri: info.uri,
917
+ version: info.version,
918
+ chainId: numericChainId,
919
+ nonce: info.nonce,
920
+ issuedAt: info.issuedAt,
921
+ expirationTime: info.expirationTime,
922
+ notBefore: info.notBefore,
923
+ requestId: info.requestId,
924
+ resources: info.resources
925
+ });
926
+ return siweMessage.prepareMessage();
927
+ }
928
+ var init_evm = __esm({
929
+ "src/server/vendor/sign-in-with-x/evm.ts"() {
930
+ }
931
+ });
932
+
933
+ // src/server/vendor/sign-in-with-x/message.ts
934
+ function createSIWxMessage(serverInfo, address) {
935
+ if (serverInfo.chainId.startsWith("eip155:")) {
936
+ return formatSIWEMessage(serverInfo, address);
937
+ }
938
+ if (serverInfo.chainId.startsWith("solana:")) {
939
+ return formatSIWSMessage(serverInfo, address);
940
+ }
941
+ throw new Error(
942
+ `Unsupported chain namespace: ${serverInfo.chainId}. Supported: eip155:* (EVM), solana:* (Solana)`
943
+ );
944
+ }
945
+ var init_message = __esm({
946
+ "src/server/vendor/sign-in-with-x/message.ts"() {
947
+ init_evm();
948
+ init_solana();
949
+ }
950
+ });
951
+
952
+ // src/server/vendor/sign-in-with-x/client.ts
953
+ async function createSIWxPayload(serverExtension, signer) {
954
+ const isSolana = serverExtension.chainId.startsWith("solana:");
955
+ const address = isSolana ? getSolanaAddress(signer) : getEVMAddress(signer);
956
+ const message = createSIWxMessage(serverExtension, address);
957
+ const signature = isSolana ? await signSolanaMessage(message, signer) : await signEVMMessage(message, signer);
958
+ return {
959
+ domain: serverExtension.domain,
960
+ address,
961
+ statement: serverExtension.statement,
962
+ uri: serverExtension.uri,
963
+ version: serverExtension.version,
964
+ chainId: serverExtension.chainId,
965
+ type: serverExtension.type,
966
+ nonce: serverExtension.nonce,
967
+ issuedAt: serverExtension.issuedAt,
968
+ expirationTime: serverExtension.expirationTime,
969
+ notBefore: serverExtension.notBefore,
970
+ requestId: serverExtension.requestId,
971
+ resources: serverExtension.resources,
972
+ signatureScheme: serverExtension.signatureScheme,
973
+ signature
974
+ };
975
+ }
976
+ var init_client = __esm({
977
+ "src/server/vendor/sign-in-with-x/client.ts"() {
978
+ init_sign();
979
+ init_message();
980
+ }
981
+ });
982
+ function encodeSIWxHeader(payload) {
983
+ return safeBase64Encode(JSON.stringify(payload));
984
+ }
985
+ var init_encode = __esm({
986
+ "src/server/vendor/sign-in-with-x/encode.ts"() {
987
+ }
988
+ });
989
+ var registerAuthTools;
990
+ var init_auth = __esm({
991
+ "src/server/tools/auth.ts"() {
992
+ init_response();
993
+ init_protocol();
994
+ init_client();
995
+ init_encode();
996
+ init_schemas();
997
+ registerAuthTools = ({ server, account }) => {
998
+ server.registerTool(
999
+ "authed_call",
1000
+ {
1001
+ description: "Make a request to a SIWX-protected endpoint. Handles auth flow automatically: detects SIWX requirement from 402 response, signs proof with server-provided challenge, retries.",
1002
+ inputSchema: requestWithHeadersSchema
1003
+ },
1004
+ async ({ url, method, body, headers }) => {
1005
+ try {
1006
+ const httpClient = new x402HTTPClient(new x402Client());
1007
+ const firstResponse = await fetch(url, {
1008
+ method,
1009
+ headers: {
1010
+ "Content-Type": "application/json",
1011
+ ...headers
1012
+ },
1013
+ body: body ? JSON.stringify(body) : void 0
1014
+ });
1015
+ if (firstResponse.status !== 402) {
1016
+ const responseHeaders2 = Object.fromEntries(
1017
+ firstResponse.headers.entries()
1018
+ );
1019
+ if (firstResponse.ok) {
1020
+ let data2;
1021
+ const contentType2 = firstResponse.headers.get("content-type");
1022
+ if (contentType2?.includes("application/json")) {
1023
+ data2 = await firstResponse.json();
1024
+ } else {
1025
+ data2 = await firstResponse.text();
1026
+ }
1027
+ return mcpSuccess({
1028
+ statusCode: firstResponse.status,
1029
+ headers: responseHeaders2,
1030
+ data: data2
1031
+ });
1032
+ }
1033
+ let errorBody;
1034
+ try {
1035
+ errorBody = await firstResponse.json();
1036
+ } catch {
1037
+ errorBody = await firstResponse.text();
1038
+ }
1039
+ return mcpError(`HTTP ${firstResponse.status}`, {
1040
+ statusCode: firstResponse.status,
1041
+ headers: responseHeaders2,
1042
+ body: errorBody
1043
+ });
1044
+ }
1045
+ let rawBody;
1046
+ try {
1047
+ rawBody = await firstResponse.clone().json();
1048
+ } catch {
1049
+ rawBody = void 0;
1050
+ }
1051
+ const rawPaymentRequired = httpClient.getPaymentRequiredResponse(
1052
+ (name) => firstResponse.headers.get(name),
1053
+ rawBody
1054
+ );
1055
+ const paymentRequired = normalizePaymentRequired(rawPaymentRequired);
1056
+ const siwxExtension = paymentRequired.extensions?.["sign-in-with-x"];
1057
+ if (!siwxExtension?.info) {
1058
+ return mcpError(
1059
+ "Endpoint returned 402 but no sign-in-with-x extension found",
1060
+ {
1061
+ statusCode: 402,
1062
+ x402Version: paymentRequired.x402Version,
1063
+ extensions: Object.keys(paymentRequired.extensions ?? {}),
1064
+ hint: "This endpoint may require payment instead of authentication. Use execute_call for paid requests."
1065
+ }
1066
+ );
1067
+ }
1068
+ const serverInfo = siwxExtension.info;
1069
+ const requiredFields = [
1070
+ "domain",
1071
+ "uri",
1072
+ "version",
1073
+ "chainId",
1074
+ "nonce",
1075
+ "issuedAt"
1076
+ ];
1077
+ const missingFields = requiredFields.filter(
1078
+ (f) => !serverInfo[f]
1079
+ );
1080
+ if (missingFields.length > 0) {
1081
+ return mcpError(
1082
+ "Invalid sign-in-with-x extension: missing required fields",
1083
+ {
1084
+ missingFields,
1085
+ receivedInfo: serverInfo
1086
+ }
1087
+ );
1088
+ }
1089
+ if (serverInfo.chainId.startsWith("solana:")) {
1090
+ return mcpError("Solana authentication not supported", {
1091
+ chainId: serverInfo.chainId,
1092
+ hint: "This endpoint requires a Solana wallet. The MCP server currently only supports EVM wallets."
1093
+ });
1094
+ }
1095
+ const payload = await createSIWxPayload(serverInfo, account);
1096
+ const siwxHeader = encodeSIWxHeader(payload);
1097
+ const authedResponse = await fetch(url, {
1098
+ method,
1099
+ headers: {
1100
+ "Content-Type": "application/json",
1101
+ "SIGN-IN-WITH-X": siwxHeader,
1102
+ ...headers
1103
+ },
1104
+ body: body ? JSON.stringify(body) : void 0
1105
+ });
1106
+ const responseHeaders = Object.fromEntries(
1107
+ authedResponse.headers.entries()
1108
+ );
1109
+ if (!authedResponse.ok) {
1110
+ let errorBody;
1111
+ try {
1112
+ errorBody = await authedResponse.json();
1113
+ } catch {
1114
+ errorBody = await authedResponse.text();
1115
+ }
1116
+ return mcpError(
1117
+ `HTTP ${authedResponse.status} after authentication`,
1118
+ {
1119
+ statusCode: authedResponse.status,
1120
+ headers: responseHeaders,
1121
+ body: errorBody,
1122
+ authAddress: account.address
1123
+ }
1124
+ );
1125
+ }
1126
+ let data;
1127
+ const contentType = authedResponse.headers.get("content-type");
1128
+ if (contentType?.includes("application/json")) {
1129
+ data = await authedResponse.json();
1130
+ } else {
1131
+ data = await authedResponse.text();
1132
+ }
1133
+ return mcpSuccess({
1134
+ statusCode: authedResponse.status,
1135
+ headers: responseHeaders,
1136
+ data,
1137
+ authentication: {
1138
+ address: account.address,
1139
+ domain: serverInfo.domain,
1140
+ chainId: serverInfo.chainId
1141
+ }
1142
+ });
1143
+ } catch (err2) {
1144
+ return mcpError(err2, { tool: "authed_call", url });
1145
+ }
1146
+ }
1147
+ );
1148
+ };
1149
+ }
1150
+ });
1151
+
1152
+ // src/server/tools/wallet.ts
1153
+ var registerWalletTools;
1154
+ var init_wallet = __esm({
1155
+ "src/server/tools/wallet.ts"() {
1156
+ init_response();
1157
+ init_balance();
1158
+ init_networks();
1159
+ init_deposit();
1160
+ registerWalletTools = ({
1161
+ server,
1162
+ account: { address },
1163
+ flags
1164
+ }) => {
1165
+ server.registerTool(
1166
+ "check_balance",
1167
+ {
1168
+ description: "Check wallet address and USDC balance. Creates wallet if needed."
1169
+ },
1170
+ async () => {
1171
+ const { balanceFormatted } = await getUSDCBalance(address, flags);
1172
+ return mcpSuccess({
1173
+ address,
1174
+ network: DEFAULT_NETWORK,
1175
+ networkName: getChainName(DEFAULT_NETWORK),
1176
+ usdcBalance: balanceFormatted,
1177
+ balanceFormatted: balanceFormatted.toString(),
1178
+ isNewWallet: balanceFormatted === 0,
1179
+ depositLink: getDepositLink(address, flags)
1180
+ });
1181
+ }
1182
+ );
1183
+ server.registerTool(
1184
+ "get_wallet_address",
1185
+ {
1186
+ description: "Get the wallet address."
1187
+ },
1188
+ () => mcpSuccess({ address })
1189
+ );
1190
+ };
1191
+ }
1192
+ });
1193
+
1194
+ // src/server/lib/x402/get-route-details.ts
1195
+ var getRouteDetails, getSchema;
1196
+ var init_get_route_details = __esm({
1197
+ "src/server/lib/x402/get-route-details.ts"() {
1198
+ init_token();
1199
+ getRouteDetails = (paymentRequired) => {
1200
+ const { accepts, extensions, resource } = paymentRequired;
1201
+ return {
1202
+ ...resource,
1203
+ schema: getSchema(extensions),
1204
+ paymentMethods: accepts.map((accept) => ({
1205
+ price: tokenStringToNumber(accept.amount),
1206
+ network: accept.network,
1207
+ asset: accept.asset
1208
+ }))
1209
+ };
1210
+ };
1211
+ getSchema = (extensions) => {
1212
+ const { bazaar } = extensions ?? {};
1213
+ if (!bazaar) {
1214
+ return void 0;
1215
+ }
1216
+ const { schema } = bazaar;
1217
+ return schema.properties.input;
1218
+ };
1219
+ }
1220
+ });
1221
+ var registerCheckX402EndpointTool;
1222
+ var init_check_endpoint_schema = __esm({
1223
+ "src/server/tools/check-endpoint-schema.ts"() {
1224
+ init_response();
1225
+ init_schemas();
1226
+ init_log();
1227
+ init_get_route_details();
1228
+ registerCheckX402EndpointTool = ({ server }) => {
1229
+ server.registerTool(
1230
+ "check_x402_endpoint",
1231
+ {
1232
+ description: "Check if an endpoint is x402-protected and get pricing options, schema, and auth requirements (if applicable).",
1233
+ inputSchema: requestSchema
1234
+ },
1235
+ async ({ url, method, body }) => {
1236
+ try {
1237
+ log.info("Querying endpoint", { url, method, body });
1238
+ const response = await fetch(url, {
1239
+ method,
1240
+ body: body ? typeof body === "string" ? body : JSON.stringify(body) : void 0,
1241
+ headers: {
1242
+ "Content-Type": "application/json"
1243
+ }
1244
+ });
1245
+ const bodyText = await response.text().catch(() => void 0);
1246
+ if (response.status !== 402) {
1247
+ return mcpSuccess({
1248
+ data: bodyText,
1249
+ statusCode: response.status,
1250
+ requiresPayment: false
1251
+ });
1252
+ }
1253
+ const paymentRequired = new x402HTTPClient(
1254
+ new x402Client()
1255
+ ).getPaymentRequiredResponse(
1256
+ (name) => response.headers.get(name),
1257
+ JSON.parse(bodyText ?? "{}")
1258
+ );
1259
+ const routeDetails = getRouteDetails(paymentRequired);
1260
+ return mcpSuccess({
1261
+ requiresPayment: true,
1262
+ statusCode: response.status,
1263
+ routeDetails
1264
+ });
1265
+ } catch (err2) {
1266
+ return mcpError(err2, { tool: "query_endpoint", url });
1267
+ }
1268
+ }
1269
+ );
1270
+ };
1271
+ }
1272
+ });
1273
+ var registerRedeemInviteTool;
1274
+ var init_redeem_invite2 = __esm({
1275
+ "src/server/tools/redeem-invite.ts"() {
1276
+ init_response();
1277
+ registerRedeemInviteTool = ({
1278
+ server,
1279
+ account: { address },
1280
+ flags
1281
+ }) => {
1282
+ const baseUrl = flags.dev ? "http://localhost:3000" : "https://x402scan.com";
1283
+ server.registerTool(
1284
+ "redeem_invite",
1285
+ {
1286
+ description: "Redeem an invite code to receive USDC.",
1287
+ inputSchema: z$1.object({
1288
+ code: z$1.string().min(1).describe("The invite code")
1289
+ })
1290
+ },
1291
+ async ({ code }) => {
1292
+ const res = await fetch(`${baseUrl}/api/invite/redeem`, {
1293
+ method: "POST",
1294
+ headers: { "Content-Type": "application/json" },
1295
+ body: JSON.stringify({ code, recipientAddr: address })
1296
+ });
1297
+ const data = await res.json();
1298
+ if (!data.success) {
1299
+ return mcpError(data.error ?? "Failed to redeem invite code");
1300
+ }
1301
+ return mcpSuccess({
1302
+ amount: `${data.amount} USDC`,
1303
+ txHash: data.txHash
1304
+ });
1305
+ }
1306
+ );
1307
+ };
1308
+ }
1309
+ });
1310
+ function getVersion() {
1311
+ {
1312
+ return "0.0.7";
1313
+ }
1314
+ }
1315
+ var MCP_VERSION, DIST_TAG;
1316
+ var init_version = __esm({
1317
+ "src/server/lib/version.ts"() {
1318
+ MCP_VERSION = getVersion();
1319
+ DIST_TAG = MCP_VERSION.includes("-beta") ? "beta" : "latest";
1320
+ }
1321
+ });
1322
+ var errorReportSchema, registerTelemetryTools;
1323
+ var init_telemetry = __esm({
1324
+ "src/server/tools/telemetry.ts"() {
1325
+ init_log();
1326
+ init_response();
1327
+ init_version();
1328
+ errorReportSchema = z.object({
1329
+ tool: z.string().describe("MCP tool name"),
1330
+ resource: z.string().optional().describe("x402 resource URL"),
1331
+ summary: z.string().describe("1-2 sentence summary"),
1332
+ errorMessage: z.string().describe("Error message"),
1333
+ stack: z.string().optional().describe("Stack trace"),
1334
+ fullReport: z.string().optional().describe("Detailed report with context, logs, repro steps")
1335
+ });
1336
+ registerTelemetryTools = ({
1337
+ server,
1338
+ account: { address },
1339
+ flags
1340
+ }) => {
1341
+ const baseUrl = flags.dev ? "http://localhost:3000" : "https://x402scan.com";
1342
+ server.registerTool(
1343
+ "report_error",
1344
+ {
1345
+ description: "EMERGENCY ONLY. Report critical MCP tool bugs. Do NOT use for normal errors (balance, network, 4xx) - those are recoverable.",
1346
+ inputSchema: errorReportSchema
1347
+ },
1348
+ async (input) => {
1349
+ try {
1350
+ log.info("Submitting error report", {
1351
+ tool: input.tool,
1352
+ resource: input.resource,
1353
+ summary: input.summary
1354
+ });
1355
+ const report = {
1356
+ ...input,
1357
+ walletAddress: address,
1358
+ mcpVersion: MCP_VERSION,
1359
+ reportedAt: (/* @__PURE__ */ new Date()).toISOString()
1360
+ };
1361
+ const response = await fetch(`${baseUrl}/api/telemetry`, {
1362
+ method: "POST",
1363
+ headers: {
1364
+ "Content-Type": "application/json"
1365
+ },
1366
+ body: JSON.stringify(report)
1367
+ });
1368
+ if (!response.ok) {
1369
+ const errorText = await response.text().catch(() => "Unknown error");
1370
+ log.error("Failed to submit error report", {
1371
+ status: response.status,
1372
+ error: errorText
1373
+ });
1374
+ return mcpError(
1375
+ `Failed to submit error report: ${response.status} ${errorText}`,
1376
+ { tool: "report_error" }
1377
+ );
1378
+ }
1379
+ const result = await response.json();
1380
+ log.info("Error report submitted successfully", {
1381
+ reportId: result.reportId
1382
+ });
1383
+ return mcpSuccess({
1384
+ submitted: true,
1385
+ reportId: result.reportId,
1386
+ message: "Error report submitted successfully. The x402scan team will investigate."
1387
+ });
1388
+ } catch (err2) {
1389
+ log.error("Failed to submit error report", { error: err2 });
1390
+ return mcpError(err2, { tool: "report_error" });
1391
+ }
1392
+ }
1393
+ );
1394
+ };
1395
+ }
1396
+ });
1397
+
1398
+ // src/server/resources/_lib.ts
1399
+ var getWebPageMetadata;
1400
+ var init_lib = __esm({
1401
+ "src/server/resources/_lib.ts"() {
1402
+ getWebPageMetadata = async (url) => {
1403
+ try {
1404
+ const response = await fetch(url);
1405
+ if (!response.ok) {
1406
+ return null;
1407
+ }
1408
+ const html = await response.text();
1409
+ const titleMatch = /<title[^>]*>([\s\S]*?)<\/title>/i.exec(html);
1410
+ const title = titleMatch ? titleMatch[1].trim().replace(/\s+/g, " ") : null;
1411
+ let descriptionMatch = /<meta\s+name=["']description["']\s+content=["']([^"']*)["']/i.exec(html);
1412
+ descriptionMatch ??= /<meta\s+property=["']og:description["']\s+content=["']([^"']*)["']/i.exec(
1413
+ html
1414
+ );
1415
+ descriptionMatch ??= /<meta\s+content=["']([^"']*)["']\s+name=["']description["']/i.exec(html);
1416
+ descriptionMatch ??= /<meta\s+content=["']([^"']*)["']\s+property=["']og:description["']/i.exec(
1417
+ html
1418
+ );
1419
+ const description = descriptionMatch ? descriptionMatch[1].trim().replace(/\s+/g, " ") : null;
1420
+ return {
1421
+ title,
1422
+ description
1423
+ };
1424
+ } catch (error) {
1425
+ throw new Error(
1426
+ `Failed to fetch web page metadata: ${error instanceof Error ? error.message : String(error)}`
1427
+ );
1428
+ }
1429
+ };
1430
+ }
1431
+ });
1432
+ var origins, registerOrigins, getResourceResponse;
1433
+ var init_origins = __esm({
1434
+ "src/server/resources/origins.ts"() {
1435
+ init_lib();
1436
+ init_get_route_details();
1437
+ origins = ["enrichx402.com"];
1438
+ registerOrigins = async ({ server }) => {
1439
+ await Promise.all(
1440
+ origins.map(async (origin) => {
1441
+ const metadata = await getWebPageMetadata(`https://${origin}`);
1442
+ server.registerResource(
1443
+ origin,
1444
+ `api://${origin}`,
1445
+ {
1446
+ title: metadata?.title ?? origin,
1447
+ description: metadata?.description ?? "",
1448
+ mimeType: "application/json"
1449
+ },
1450
+ async (uri) => {
1451
+ const response = await fetch(
1452
+ `${uri.toString().replace("api://", "https://")}/.well-known/x402`
1453
+ ).then((response2) => response2.json());
1454
+ const resources = await Promise.all(
1455
+ response.resources.map(async (resource) => {
1456
+ const resourceResponse = await getResourceResponse(
1457
+ resource,
1458
+ await fetch(resource, {
1459
+ method: "POST",
1460
+ headers: {
1461
+ "Content-Type": "application/json"
1462
+ }
1463
+ })
1464
+ );
1465
+ if (resourceResponse) {
1466
+ return resourceResponse;
1467
+ }
1468
+ const getResponse = await getResourceResponse(
1469
+ resource,
1470
+ await fetch(resource, {
1471
+ method: "GET"
1472
+ })
1473
+ );
1474
+ if (getResponse) {
1475
+ return getResponse;
1476
+ }
1477
+ console.error(`Failed to get resource response for ${resource}`);
1478
+ return null;
1479
+ })
1480
+ );
1481
+ return {
1482
+ contents: [
1483
+ {
1484
+ uri: origin,
1485
+ text: JSON.stringify({
1486
+ server: origin,
1487
+ name: metadata?.title,
1488
+ description: metadata?.description,
1489
+ resources: resources.filter(Boolean).map((resource) => {
1490
+ if (!resource) return null;
1491
+ const schema = getSchema(
1492
+ resource.paymentRequired?.extensions
1493
+ );
1494
+ return {
1495
+ url: resource.resource,
1496
+ schema,
1497
+ mimeType: resource.paymentRequired.resource.mimeType
1498
+ };
1499
+ })
1500
+ }),
1501
+ mimeType: "application/json"
1502
+ }
1503
+ ]
1504
+ };
1505
+ }
1506
+ );
1507
+ })
1508
+ );
1509
+ };
1510
+ getResourceResponse = async (resource, response) => {
1511
+ const client = new x402HTTPClient(new x402Client());
1512
+ if (response.status === 402) {
1513
+ const paymentRequired = client.getPaymentRequiredResponse(
1514
+ (name) => response.headers.get(name),
1515
+ JSON.parse(await response.text())
1516
+ );
1517
+ return {
1518
+ paymentRequired,
1519
+ resource
1520
+ };
1521
+ }
1522
+ return null;
1523
+ };
1524
+ }
1525
+ });
1526
+ async function getWallet() {
1527
+ if (process.env.X402_PRIVATE_KEY) {
1528
+ const account2 = privateKeyToAccount(process.env.X402_PRIVATE_KEY);
1529
+ log.info(`Using wallet from env: ${account2.address}`);
1530
+ return { account: account2, isNew: false };
1531
+ }
1532
+ try {
1533
+ const data = await fs3.readFile(WALLET_FILE, "utf-8");
1534
+ const stored2 = storedWalletSchema.parse(JSON.parse(data));
1535
+ const account2 = privateKeyToAccount(stored2.privateKey);
1536
+ log.info(`Loaded wallet: ${account2.address}`);
1537
+ return { account: account2, isNew: false };
1538
+ } catch {
1539
+ }
1540
+ const privateKey = `0x${randomBytes(32).toString("hex")}`;
1541
+ const account = privateKeyToAccount(privateKey);
1542
+ const stored = {
1543
+ privateKey,
1544
+ address: account.address,
1545
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1546
+ };
1547
+ await fs3.writeFile(WALLET_FILE, JSON.stringify(stored, null, 2));
1548
+ try {
1549
+ await fs3.chmod(WALLET_FILE, 384);
1550
+ } catch {
1551
+ }
1552
+ log.info(`Created wallet: ${account.address}`);
1553
+ log.info(`Saved to: ${WALLET_FILE}`);
1554
+ return { account, isNew: true };
1555
+ }
1556
+ var WALLET_FILE, storedWalletSchema;
1557
+ var init_wallet2 = __esm({
1558
+ "src/lib/wallet.ts"() {
1559
+ init_log();
1560
+ init_schemas();
1561
+ init_fs();
1562
+ WALLET_FILE = configFile("wallet.json");
1563
+ storedWalletSchema = z$1.object({
1564
+ privateKey: ethereumPrivateKeySchema,
1565
+ address: ethereumAddressSchema,
1566
+ createdAt: z$1.string()
1567
+ });
1568
+ }
1569
+ });
1570
+ async function lookupDnsTxtRecord(hostname) {
1571
+ const dnsQuery = `_x402.${hostname}`;
1572
+ log.debug(`Looking up DNS TXT record: ${dnsQuery}`);
1573
+ try {
1574
+ const response = await fetch(
1575
+ `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(
1576
+ dnsQuery
1577
+ )}&type=TXT`,
1578
+ {
1579
+ headers: { Accept: "application/dns-json" }
1580
+ }
1581
+ );
1582
+ if (!response.ok) {
1583
+ log.debug(`DNS lookup failed: HTTP ${response.status}`);
1584
+ return null;
1585
+ }
1586
+ const data = await response.json();
1587
+ if (!data.Answer || data.Answer.length === 0) {
1588
+ log.debug("No DNS TXT record found");
1589
+ return null;
1590
+ }
1591
+ const txtValue = data.Answer[0].data.replace(/^"|"$/g, "");
1592
+ log.debug(`Found DNS TXT record: ${txtValue}`);
1593
+ try {
1594
+ new URL(txtValue);
1595
+ return txtValue;
1596
+ } catch {
1597
+ log.debug(`DNS TXT value is not a valid URL: ${txtValue}`);
1598
+ return null;
1599
+ }
1600
+ } catch (err2) {
1601
+ log.debug(
1602
+ `DNS lookup error: ${err2 instanceof Error ? err2.message : String(err2)}`
1603
+ );
1604
+ return null;
1605
+ }
1606
+ }
1607
+ async function fetchLlmsTxt(origin) {
1608
+ const llmsTxtUrl = `${origin}/llms.txt`;
1609
+ log.debug(`Fetching llms.txt from: ${llmsTxtUrl}`);
1610
+ try {
1611
+ const response = await fetch(llmsTxtUrl, {
1612
+ headers: { Accept: "text/plain" }
1613
+ });
1614
+ if (!response.ok) {
1615
+ if (response.status === 404) {
1616
+ return { found: false, error: "No llms.txt found" };
1617
+ }
1618
+ return { found: false, error: `HTTP ${response.status}` };
1619
+ }
1620
+ const content = await response.text();
1621
+ if (!content || content.trim().length === 0) {
1622
+ return { found: false, error: "llms.txt is empty" };
1623
+ }
1624
+ return { found: true, content };
1625
+ } catch (err2) {
1626
+ return {
1627
+ found: false,
1628
+ error: `Network error: ${err2 instanceof Error ? err2.message : String(err2)}`
1629
+ };
1630
+ }
1631
+ }
1632
+ async function fetchDiscoveryFromUrl(url) {
1633
+ log.debug(`Fetching discovery document from: ${url}`);
1634
+ try {
1635
+ const response = await fetch(url, {
1636
+ headers: { Accept: "application/json" }
1637
+ });
1638
+ if (!response.ok) {
1639
+ if (response.status === 404) {
1640
+ return { found: false, error: `Not found at ${url}` };
1641
+ }
1642
+ return {
1643
+ found: false,
1644
+ error: `HTTP ${response.status}: ${await response.text()}`
1645
+ };
1646
+ }
1647
+ let rawData;
1648
+ try {
1649
+ rawData = await response.json();
1650
+ } catch {
1651
+ return {
1652
+ found: false,
1653
+ error: "Failed to parse discovery document as JSON"
1654
+ };
1655
+ }
1656
+ const parsed = DiscoveryDocumentSchema.safeParse(rawData);
1657
+ if (!parsed.success) {
1658
+ return {
1659
+ found: false,
1660
+ error: `Invalid discovery document: ${parsed.error.issues.map((e) => e.message).join(", ")}`,
1661
+ rawResponse: rawData
1662
+ };
1663
+ }
1664
+ return { found: true, document: parsed.data };
1665
+ } catch (err2) {
1666
+ return {
1667
+ found: false,
1668
+ error: `Network error: ${err2 instanceof Error ? err2.message : String(err2)}`
1669
+ };
1670
+ }
1671
+ }
1672
+ async function fetchDiscoveryDocument(origin) {
1673
+ const attemptedSources = [];
1674
+ const hostname = getHostname(origin);
1675
+ const wellKnownUrl = `${origin}/.well-known/x402`;
1676
+ attemptedSources.push(wellKnownUrl);
1677
+ const wellKnownResult = await fetchDiscoveryFromUrl(wellKnownUrl);
1678
+ if (wellKnownResult.found && wellKnownResult.document) {
1679
+ return {
1680
+ found: true,
1681
+ source: "well-known",
1682
+ document: wellKnownResult.document,
1683
+ attemptedSources
1684
+ };
1685
+ }
1686
+ attemptedSources.push(`DNS TXT _x402.${hostname}`);
1687
+ const dnsUrl = await lookupDnsTxtRecord(hostname);
1688
+ if (dnsUrl) {
1689
+ attemptedSources.push(dnsUrl);
1690
+ const dnsResult = await fetchDiscoveryFromUrl(dnsUrl);
1691
+ if (dnsResult.found && dnsResult.document) {
1692
+ return {
1693
+ found: true,
1694
+ source: "dns-txt",
1695
+ document: dnsResult.document,
1696
+ attemptedSources
1697
+ };
1698
+ }
1699
+ }
1700
+ attemptedSources.push(`${origin}/llms.txt`);
1701
+ const llmsResult = await fetchLlmsTxt(origin);
1702
+ if (llmsResult.found && llmsResult.content) {
1703
+ return {
1704
+ found: true,
1705
+ source: "llms-txt",
1706
+ llmsTxtContent: llmsResult.content,
1707
+ attemptedSources
1708
+ };
1709
+ }
1710
+ return {
1711
+ found: false,
1712
+ error: "No discovery document found. Tried: .well-known/x402, DNS TXT record, llms.txt",
1713
+ attemptedSources
1714
+ };
1715
+ }
1716
+ async function queryResource(url) {
1717
+ log.debug(`Querying resource: ${url}`);
1718
+ try {
1719
+ const result = await fetch(url, { method: "GET" });
1720
+ if (!result.ok) {
1721
+ return {
1722
+ url,
1723
+ isX402Endpoint: false,
1724
+ error: result.statusText ?? "Failed to query endpoint"
1725
+ };
1726
+ }
1727
+ if (result.status !== 402) {
1728
+ return {
1729
+ url,
1730
+ isX402Endpoint: false
1731
+ };
1732
+ }
1733
+ const pr = new x402HTTPClient(new x402Client()).getPaymentRequiredResponse(
1734
+ (name) => result.headers.get(name),
1735
+ JSON.parse(await result.text())
1736
+ );
1737
+ const firstReq = pr.accepts[0];
1738
+ const resource = {
1739
+ url,
1740
+ isX402Endpoint: true,
1741
+ x402Version: pr.x402Version,
1742
+ price: tokenStringToNumber(firstReq.amount),
1743
+ priceRaw: firstReq.amount,
1744
+ network: firstReq.network,
1745
+ networkName: getChainName(firstReq.network)
1746
+ };
1747
+ if (pr.extensions?.bazaar) {
1748
+ const bazaar = pr.extensions.bazaar;
1749
+ resource.bazaar = { info: bazaar.info, schema: bazaar.schema };
1750
+ const info = bazaar.info;
1751
+ if (info?.description) {
1752
+ resource.description = info.description;
1753
+ }
1754
+ }
1755
+ if (pr.extensions?.["sign-in-with-x"]) {
1756
+ const siwx = pr.extensions["sign-in-with-x"];
1757
+ resource.signInWithX = { required: true, info: siwx.info };
1758
+ }
1759
+ return resource;
1760
+ } catch (err2) {
1761
+ return {
1762
+ url,
1763
+ isX402Endpoint: false,
1764
+ error: err2 instanceof Error ? err2.message : String(err2)
1765
+ };
1766
+ }
1767
+ }
1768
+ function registerDiscoveryTools(server) {
1769
+ server.registerTool(
1770
+ "discover_resources",
1771
+ {
1772
+ description: `Discover x402-protected resources on an origin.
1773
+ NEVER use 'fanOut = true' on the first try.
1774
+ NEVER use 'fanOut = true' when there are more than 8 resources.
1775
+
1776
+ Known default origins with resource packs. Discover if more needed:
1777
+ - https://enrichx402.com ->
1778
+ People + Org search
1779
+ Google Maps (places + locations)
1780
+ Grok twitter search
1781
+ Exa web search
1782
+ Clado linkedin data
1783
+ Firecrawl web scrape
1784
+ - https://stablestudio.io -> generate images / videos
1785
+ `,
1786
+ inputSchema: {
1787
+ url: z.url().describe(
1788
+ "The origin URL or any URL on the origin to discover resources from"
1789
+ ),
1790
+ fanOut: z.boolean().default(false).describe(
1791
+ "Whether to query each discovered resource for full pricing/schema info. NEVER use on first try."
1792
+ ),
1793
+ concurrency: z.number().int().min(1).max(10).default(5).describe(
1794
+ "Max concurrent requests when querying resources (default: 5)"
1795
+ )
1796
+ }
1797
+ },
1798
+ async ({ url, fanOut, concurrency }) => {
1799
+ try {
1800
+ const origin = getOrigin(url);
1801
+ log.info(`Discovering resources for origin: ${origin}`);
1802
+ const discoveryResult = await fetchDiscoveryDocument(origin);
1803
+ if (discoveryResult.found && discoveryResult.source === "llms-txt") {
1804
+ return mcpSuccess({
1805
+ found: true,
1806
+ origin,
1807
+ source: "llms-txt",
1808
+ usage: "Found llms.txt but no structured x402 discovery document. The content below may contain information about x402 resources. Parse it to find relevant endpoints.",
1809
+ llmsTxtContent: discoveryResult.llmsTxtContent,
1810
+ attemptedSources: discoveryResult.attemptedSources,
1811
+ resources: []
1812
+ });
1813
+ }
1814
+ if (!discoveryResult.found || !discoveryResult.document) {
1815
+ return mcpSuccess({
1816
+ found: false,
1817
+ origin,
1818
+ error: discoveryResult.error,
1819
+ attemptedSources: discoveryResult.attemptedSources,
1820
+ rawResponse: discoveryResult.rawResponse
1821
+ });
1822
+ }
1823
+ const doc = discoveryResult.document;
1824
+ const result = {
1825
+ found: true,
1826
+ origin,
1827
+ source: discoveryResult.source,
1828
+ instructions: doc.instructions,
1829
+ usage: "Use query_endpoint to get full pricing/requirements for a resource. Use execute_call (for payment) or authed_call (for SIWX auth) to call it.",
1830
+ resources: []
1831
+ };
1832
+ if (!fanOut) {
1833
+ result.resources = doc.resources.map((resourceUrl) => ({
1834
+ url: resourceUrl
1835
+ }));
1836
+ return mcpSuccess(result);
1837
+ }
1838
+ const resourceUrls = doc.resources;
1839
+ const allResources = [];
1840
+ for (let i = 0; i < resourceUrls.length; i += concurrency) {
1841
+ const batch = resourceUrls.slice(i, i + concurrency);
1842
+ const batchResults = await Promise.all(
1843
+ batch.map((resourceUrl) => queryResource(resourceUrl))
1844
+ );
1845
+ allResources.push(...batchResults);
1846
+ }
1847
+ result.resources = allResources;
1848
+ return mcpSuccess(result);
1849
+ } catch (err2) {
1850
+ return mcpError(err2, { tool: "discover_resources", url });
1851
+ }
1852
+ }
1853
+ );
1854
+ }
1855
+ function getOrigin(urlString) {
1856
+ try {
1857
+ return new URL(urlString).origin;
1858
+ } catch {
1859
+ return urlString;
1860
+ }
1861
+ }
1862
+ function getHostname(origin) {
1863
+ try {
1864
+ return new URL(origin).hostname;
1865
+ } catch {
1866
+ return origin;
1867
+ }
1868
+ }
1869
+ var DiscoveryDocumentSchema;
1870
+ var init_discover_resources = __esm({
1871
+ "src/server/tools/discover-resources.ts"() {
1872
+ init_log();
1873
+ init_response();
1874
+ init_token();
1875
+ init_networks();
1876
+ DiscoveryDocumentSchema = z.object({
1877
+ version: z.number().refine((v) => v === 1, { message: "version must be 1" }),
1878
+ resources: z.array(z.url()),
1879
+ ownershipProofs: z.array(z.string()).optional(),
1880
+ instructions: z.string().optional()
1881
+ });
1882
+ }
1883
+ });
1884
+
1885
+ // src/server/index.ts
1886
+ var server_exports = {};
1887
+ __export(server_exports, {
1888
+ startServer: () => startServer
1889
+ });
1890
+ var startServer;
1891
+ var init_server = __esm({
1892
+ "src/server/index.ts"() {
1893
+ init_fetch_x402_resource();
1894
+ init_auth();
1895
+ init_wallet();
1896
+ init_check_endpoint_schema();
1897
+ init_redeem_invite2();
1898
+ init_telemetry();
1899
+ init_origins();
1900
+ init_log();
1901
+ init_wallet2();
1902
+ init_discover_resources();
1903
+ init_redeem_invite();
1904
+ init_version();
1905
+ startServer = async (flags) => {
1906
+ log.info("Starting x402scan-mcp...");
1907
+ const { dev, invite } = flags;
1908
+ const { account } = await getWallet();
1909
+ const code = invite ?? process.env.INVITE_CODE;
1910
+ const sessionId = randomBytes(16).toString("hex");
1911
+ if (code) {
1912
+ await redeemInviteCode({
1913
+ code,
1914
+ dev,
1915
+ address: account.address
1916
+ });
1917
+ }
1918
+ const server = new McpServer(
1919
+ {
1920
+ name: "@x402scan/mcp",
1921
+ version: MCP_VERSION,
1922
+ websiteUrl: "https://x402scan.com/mcp",
1923
+ icons: [{ src: "https://x402scan.com/logo.svg" }]
1924
+ },
1925
+ {
1926
+ capabilities: {
1927
+ resources: {
1928
+ subscribe: true,
1929
+ listChanged: true
1930
+ }
1931
+ }
1932
+ }
1933
+ );
1934
+ const props = {
1935
+ server,
1936
+ account,
1937
+ flags,
1938
+ sessionId
1939
+ };
1940
+ registerFetchX402ResourceTool(props);
1941
+ registerAuthTools(props);
1942
+ registerWalletTools(props);
1943
+ registerCheckX402EndpointTool(props);
1944
+ registerRedeemInviteTool(props);
1945
+ registerDiscoveryTools(server);
1946
+ registerTelemetryTools(props);
1947
+ await registerOrigins({ server, flags });
1948
+ const transport = new StdioServerTransport();
1949
+ await server.connect(transport);
1950
+ const shutdown = async () => {
1951
+ log.info("Shutting down...");
1952
+ await server.close();
1953
+ process.exit(0);
1954
+ };
1955
+ process.on("SIGINT", () => void shutdown());
1956
+ process.on("SIGTERM", () => void shutdown());
1957
+ };
1958
+ }
1959
+ });
1960
+ var getClient;
1961
+ var init_get_client = __esm({
1962
+ "src/install/1-get-client/index.ts"() {
1963
+ init_clients();
1964
+ getClient = async ({ client: flagClient, yes }) => {
1965
+ if (yes) {
1966
+ if (!flagClient) {
1967
+ throw new Error(
1968
+ `Client is required when yes is true. Pass --client as one of these values: ${Object.values(Clients).join(", ")}`
1969
+ );
1970
+ }
1971
+ const parsedClient2 = z$1.enum(Clients).safeParse(flagClient);
1972
+ if (!parsedClient2.success) {
1973
+ throw new Error(
1974
+ `${flagClient} is not a valid client. Valid options are: ${Object.values(Clients).join(", ")}`
1975
+ );
1976
+ }
1977
+ return parsedClient2.data;
1978
+ }
1979
+ const parsedClient = z$1.enum(Clients).safeParse(flagClient);
1980
+ if (parsedClient.success) {
1981
+ return parsedClient.data;
1982
+ }
1983
+ if (flagClient) {
1984
+ log$1.error(`${flagClient} is not a valid client. Please select a client`);
1985
+ }
1986
+ const client = await select({
1987
+ message: "Where would you like to install the x402scan MCP server?",
1988
+ options: Object.values(Clients).map((client2) => {
1989
+ const metadata = clientMetadata[client2];
1990
+ return {
1991
+ label: metadata.name,
1992
+ value: client2
1993
+ };
1994
+ }),
1995
+ maxItems: 7
1996
+ });
1997
+ const parsedClientSelection = z$1.enum(Clients).safeParse(client);
1998
+ if (parsedClientSelection.success) {
1999
+ return parsedClientSelection.data;
2000
+ }
2001
+ outro(chalk.bold.red("No MCP client selected"));
2002
+ process.exit(0);
2003
+ };
2004
+ }
2005
+ });
2006
+ var Platforms, getPlatformPath;
2007
+ var init_platforms = __esm({
2008
+ "src/install/2-add-server/lib/platforms.ts"() {
2009
+ Platforms = /* @__PURE__ */ ((Platforms2) => {
2010
+ Platforms2["Windows"] = "win32";
2011
+ Platforms2["MacOS"] = "darwin";
2012
+ Platforms2["Linux"] = "linux";
2013
+ return Platforms2;
2014
+ })(Platforms || {});
2015
+ getPlatformPath = () => {
2016
+ const platform = z$1.enum(Platforms).safeParse(process2.platform);
2017
+ if (!platform.success) {
2018
+ throw new Error(`Invalid platform: ${process2.platform}`);
2019
+ }
2020
+ const homeDir = os.homedir();
2021
+ switch (platform.data) {
2022
+ case "win32" /* Windows */:
2023
+ return {
2024
+ baseDir: process2.env.APPDATA ?? path2.join(homeDir, "AppData", "Roaming"),
2025
+ vscodePath: path2.join("Code", "User")
2026
+ };
2027
+ case "darwin" /* MacOS */:
2028
+ return {
2029
+ baseDir: path2.join(homeDir, "Library", "Application Support"),
2030
+ vscodePath: path2.join("Code", "User")
2031
+ };
2032
+ case "linux" /* Linux */:
2033
+ return {
2034
+ baseDir: process2.env.XDG_CONFIG_HOME ?? path2.join(homeDir, ".config"),
2035
+ vscodePath: path2.join("Code/User")
2036
+ };
2037
+ default:
2038
+ throw new Error(`Invalid platform: ${process2.platform}`);
2039
+ }
2040
+ };
2041
+ }
2042
+ });
2043
+ var parseClientConfig, serializeClientConfig, stringifyObject;
2044
+ var init_file_types = __esm({
2045
+ "src/install/2-add-server/lib/file-types.ts"() {
2046
+ parseClientConfig = ({ format: format2, path: path3 }) => {
2047
+ const fileContent = fs__default.readFileSync(path3, "utf8");
2048
+ let config = {};
2049
+ if (format2 === "yaml" /* YAML */) {
2050
+ config = yaml.load(fileContent);
2051
+ } else if (format2 === "toml" /* TOML */) {
2052
+ config = TOML.parse(fileContent);
2053
+ } else if (path3.endsWith(".jsonc")) {
2054
+ config = jsonc.parse(fileContent);
2055
+ } else {
2056
+ config = JSON.parse(fileContent);
2057
+ }
2058
+ return {
2059
+ config,
2060
+ fileContent
2061
+ };
2062
+ };
2063
+ serializeClientConfig = ({ format: format2, path: path3 }, config, originalContent) => {
2064
+ if (format2 === "yaml" /* YAML */) {
2065
+ return yaml.dump(config, {
2066
+ indent: 2,
2067
+ lineWidth: -1,
2068
+ noRefs: true
2069
+ });
2070
+ }
2071
+ if (format2 === "toml" /* TOML */) {
2072
+ return TOML.stringify(config);
2073
+ }
2074
+ if (path3.endsWith(".jsonc") && originalContent) {
2075
+ try {
2076
+ const editedContent = originalContent;
2077
+ const modifications = [];
2078
+ for (const key of Object.keys(config)) {
2079
+ const path4 = [key];
2080
+ const edits = jsonc.modify(editedContent, path4, config[key], {
2081
+ formattingOptions: { tabSize: 2, insertSpaces: true }
2082
+ });
2083
+ modifications.push(...edits);
2084
+ }
2085
+ return jsonc.applyEdits(originalContent, modifications);
2086
+ } catch (error) {
2087
+ console.log(
2088
+ `Error applying JSONC edits: ${error instanceof Error ? error.message : String(error)}`
2089
+ );
2090
+ console.log("Falling back to JSON.stringify (comments will be lost)");
2091
+ return JSON.stringify(config, null, 2);
2092
+ }
2093
+ }
2094
+ return JSON.stringify(config, null, 2);
2095
+ };
2096
+ stringifyObject = (config, format2) => {
2097
+ if (format2 === "yaml" /* YAML */) {
2098
+ return yaml.dump(config, {
2099
+ indent: 2,
2100
+ lineWidth: -1,
2101
+ noRefs: true
2102
+ });
2103
+ }
2104
+ if (format2 === "toml" /* TOML */) {
2105
+ return TOML.stringify(config);
2106
+ }
2107
+ return JSON.stringify(config, null, 2);
2108
+ };
2109
+ }
2110
+ });
2111
+ var getClientConfigFile;
2112
+ var init_client_config_file = __esm({
2113
+ "src/install/2-add-server/lib/client-config-file.ts"() {
2114
+ init_platforms();
2115
+ init_log();
2116
+ init_clients();
2117
+ init_file_types();
2118
+ getClientConfigFile = (client) => {
2119
+ const homeDir = os.homedir();
2120
+ const { baseDir, vscodePath } = getPlatformPath();
2121
+ switch (client) {
2122
+ case "claude" /* Claude */:
2123
+ return {
2124
+ path: path2.join(baseDir, "Claude", "claude_desktop_config.json"),
2125
+ configKey: "mcpServers",
2126
+ format: "json" /* JSON */
2127
+ };
2128
+ case "cline" /* Cline */:
2129
+ return {
2130
+ path: path2.join(
2131
+ baseDir,
2132
+ vscodePath,
2133
+ "globalStorage",
2134
+ "saoudrizwan.claude-dev",
2135
+ "settings",
2136
+ "cline_mcp_settings.json"
2137
+ ),
2138
+ configKey: "mcpServers",
2139
+ format: "json" /* JSON */
2140
+ };
2141
+ case "roo-cline" /* RooCline */:
2142
+ return {
2143
+ path: path2.join(
2144
+ baseDir,
2145
+ vscodePath,
2146
+ "globalStorage",
2147
+ "rooveterinaryinc.roo-cline",
2148
+ "settings",
2149
+ "mcp_settings.json"
2150
+ ),
2151
+ configKey: "mcpServers",
2152
+ format: "json" /* JSON */
2153
+ };
2154
+ case "windsurf" /* Windsurf */:
2155
+ return {
2156
+ path: path2.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
2157
+ configKey: "mcpServers",
2158
+ format: "json" /* JSON */
2159
+ };
2160
+ case "cursor" /* Cursor */:
2161
+ return {
2162
+ path: path2.join(homeDir, ".cursor", "mcp.json"),
2163
+ configKey: "mcpServers",
2164
+ format: "json" /* JSON */
2165
+ };
2166
+ case "warp" /* Warp */:
2167
+ return {
2168
+ path: "no-local-config",
2169
+ // it's okay this isn't a real path, we never use it
2170
+ configKey: "mcpServers",
2171
+ format: "json" /* JSON */
2172
+ };
2173
+ case "gemini-cli" /* GeminiCli */:
2174
+ return {
2175
+ path: path2.join(homeDir, ".gemini", "settings.json"),
2176
+ configKey: "mcpServers",
2177
+ format: "json" /* JSON */
2178
+ };
2179
+ case "vscode" /* Vscode */:
2180
+ return {
2181
+ path: path2.join(baseDir, vscodePath, "mcp.json"),
2182
+ configKey: "mcpServers",
2183
+ format: "json" /* JSON */
2184
+ };
2185
+ case "claude-code" /* ClaudeCode */:
2186
+ return {
2187
+ path: path2.join(homeDir, ".claude.json"),
2188
+ configKey: "mcpServers",
2189
+ format: "json" /* JSON */
2190
+ };
2191
+ case "goose" /* Goose */:
2192
+ return {
2193
+ path: path2.join(homeDir, ".config", "goose", "config.yaml"),
2194
+ configKey: "extensions",
2195
+ format: "yaml" /* YAML */
2196
+ };
2197
+ case "zed" /* Zed */:
2198
+ return {
2199
+ path: process2.platform === "win32" ? path2.join(
2200
+ process2.env.APPDATA ?? path2.join(homeDir, "AppData", "Roaming"),
2201
+ "Zed",
2202
+ "settings.json"
2203
+ ) : path2.join(homeDir, ".config", "zed", "settings.json"),
2204
+ configKey: "context_servers",
2205
+ format: "json" /* JSON */
2206
+ };
2207
+ case "codex" /* Codex */:
2208
+ return {
2209
+ path: path2.join(
2210
+ process2.env.CODEX_HOME ?? path2.join(homeDir, ".codex"),
2211
+ "config.toml"
2212
+ ),
2213
+ configKey: "mcp_servers",
2214
+ format: "toml" /* TOML */
2215
+ };
2216
+ case "opencode" /* Opencode */: {
2217
+ const jsonPath = path2.join(
2218
+ homeDir,
2219
+ ".config",
2220
+ "opencode",
2221
+ "opencode.json"
2222
+ );
2223
+ const jsoncPath = jsonPath.replace(".json", ".jsonc");
2224
+ if (fs__default.existsSync(jsoncPath)) {
2225
+ log.info(`Found .jsonc file for OpenCode, using: ${jsoncPath}`);
2226
+ return {
2227
+ path: jsoncPath,
2228
+ configKey: "mcp",
2229
+ format: "json" /* JSON */
2230
+ };
2231
+ }
2232
+ return {
2233
+ path: jsonPath,
2234
+ configKey: "mcp",
2235
+ format: "json" /* JSON */
2236
+ };
2237
+ }
2238
+ default:
2239
+ throw new Error(`Unknown client: ${String(client)}`);
2240
+ }
2241
+ };
2242
+ }
2243
+ });
2244
+
2245
+ // src/install/2-add-server/lib/nested-values.ts
2246
+ var getNestedValue, setNestedValue;
2247
+ var init_nested_values = __esm({
2248
+ "src/install/2-add-server/lib/nested-values.ts"() {
2249
+ getNestedValue = (obj, path3) => {
2250
+ const keys = path3.split(".");
2251
+ let current = obj;
2252
+ for (const key of keys) {
2253
+ if (current && typeof current === "object" && key in current) {
2254
+ current = current[key];
2255
+ } else {
2256
+ return void 0;
2257
+ }
2258
+ }
2259
+ return current;
2260
+ };
2261
+ setNestedValue = (obj, path3, value) => {
2262
+ const keys = path3.split(".");
2263
+ const lastKey = keys.pop();
2264
+ if (!lastKey) return;
2265
+ const target = keys.reduce((current, key) => {
2266
+ current[key] ??= {};
2267
+ return current[key];
2268
+ }, obj);
2269
+ target[lastKey] = value;
2270
+ };
2271
+ }
2272
+ });
2273
+
2274
+ // src/install/2-add-server/lib/index.ts
2275
+ var init_lib2 = __esm({
2276
+ "src/install/2-add-server/lib/index.ts"() {
2277
+ init_client_config_file();
2278
+ init_file_types();
2279
+ init_nested_values();
2280
+ init_platforms();
2281
+ }
2282
+ });
2283
+ async function addServer(client, globalFlags) {
2284
+ const { serverName, command, args } = getMcpConfig(globalFlags);
2285
+ if (client === "warp" /* Warp */) {
2286
+ log$1.info(
2287
+ chalk.bold.yellow("Warp requires a manual installation through their UI.")
2288
+ );
2289
+ log$1.message(
2290
+ "Please copy the following configuration object and add it to your Warp MCP config:"
2291
+ );
2292
+ console.log();
2293
+ console.log(
2294
+ JSON.stringify(
2295
+ {
2296
+ [serverName]: {
2297
+ command,
2298
+ args,
2299
+ working_directory: null,
2300
+ start_on_launch: true
2301
+ }
2302
+ },
2303
+ null,
2304
+ 2
2305
+ )
2306
+ );
2307
+ console.log();
2308
+ log$1.message(
2309
+ `Read Warp's documentation at https://docs.warp.dev/knowledge-and-collaboration/mcp`
2310
+ );
2311
+ const addedToWarp = await confirm({
2312
+ message: "Did you add the MCP server to your Warp config?"
2313
+ });
2314
+ if (!addedToWarp) {
2315
+ throw new Error("Warp MCP server not added");
2316
+ }
2317
+ }
2318
+ const clientFileTarget = getClientConfigFile(client);
2319
+ const { name } = clientMetadata[client];
2320
+ try {
2321
+ let config = {};
2322
+ let content = void 0;
2323
+ log.info(`Checking if config file exists at: ${clientFileTarget.path}`);
2324
+ if (!fs__default.existsSync(clientFileTarget.path)) {
2325
+ log.info("Config file not found, creating default empty config");
2326
+ setNestedValue(config, clientFileTarget.configKey, {});
2327
+ log.info("Config created successfully");
2328
+ if (!globalFlags.yes) {
2329
+ await wait({
2330
+ startText: "Locating config file",
2331
+ stopText: `No config found, creating default empty config`,
2332
+ ms: 1e3
2333
+ });
2334
+ }
2335
+ } else {
2336
+ log.info("Config file found, reading config file content");
2337
+ const { config: rawConfig, fileContent } = parseClientConfig(clientFileTarget);
2338
+ config = rawConfig;
2339
+ content = fileContent;
2340
+ const existingValue = getNestedValue(
2341
+ rawConfig,
2342
+ clientFileTarget.configKey
2343
+ );
2344
+ if (!existingValue) {
2345
+ setNestedValue(rawConfig, clientFileTarget.configKey, {});
2346
+ }
2347
+ log.info(
2348
+ `Config loaded successfully: ${JSON.stringify(rawConfig, null, 2)}`
2349
+ );
2350
+ if (!globalFlags.yes) {
2351
+ await wait({
2352
+ startText: `Locating config file`,
2353
+ stopText: `Config loaded from ${clientFileTarget.path}`,
2354
+ ms: 1e3
2355
+ });
2356
+ }
2357
+ }
2358
+ const servers = getNestedValue(config, clientFileTarget.configKey);
2359
+ if (!servers || typeof servers !== "object") {
2360
+ log.error(`Invalid ${clientFileTarget.configKey} structure in config`);
2361
+ log$1.error(
2362
+ chalk.bold.red(
2363
+ `Invalid ${clientFileTarget.configKey} structure in config`
2364
+ )
2365
+ );
2366
+ throw new Error(`Invalid ${clientFileTarget.configKey} structure`);
2367
+ }
2368
+ if (client === "goose" /* Goose */) {
2369
+ servers[serverName] = {
2370
+ name: serverName,
2371
+ cmd: command,
2372
+ args,
2373
+ enabled: true,
2374
+ envs: {},
2375
+ type: "stdio",
2376
+ timeout: 300
2377
+ };
2378
+ } else if (client === "zed" /* Zed */) {
2379
+ servers[serverName] = {
2380
+ source: "custom",
2381
+ command,
2382
+ args,
2383
+ env: {}
2384
+ };
2385
+ } else if (client === "opencode" /* Opencode */) {
2386
+ servers[serverName] = {
2387
+ type: "local",
2388
+ command,
2389
+ args,
2390
+ enabled: true,
2391
+ environment: {}
2392
+ };
2393
+ } else {
2394
+ servers[serverName] = {
2395
+ command,
2396
+ args
2397
+ };
2398
+ }
2399
+ if (!globalFlags.yes) {
2400
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2401
+ }
2402
+ if (!globalFlags.yes) {
2403
+ log$1.step(
2404
+ `The following will be added to ${chalk.bold.underline(clientFileTarget.path)}`
2405
+ );
2406
+ }
2407
+ const configStr = formatDiffByFormat(
2408
+ {
2409
+ [clientFileTarget.configKey]: {
2410
+ [serverName]: servers[serverName]
2411
+ }
2412
+ },
2413
+ clientFileTarget.format
2414
+ );
2415
+ if (!globalFlags.yes) {
2416
+ await stream.message(
2417
+ (async function* () {
2418
+ for (const num of Array.from(
2419
+ { length: configStr.length },
2420
+ (_, i) => i
2421
+ )) {
2422
+ const char = configStr[num];
2423
+ yield char;
2424
+ if (!["\n", " ", "\u2500", "\u256E", "\u256D", "\u2570", "\u256F", "\u2502"].includes(char)) {
2425
+ await new Promise((resolve) => setTimeout(resolve, 5));
2426
+ } else {
2427
+ await new Promise((resolve) => setTimeout(resolve, 2));
2428
+ }
2429
+ }
2430
+ })()
2431
+ );
2432
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2433
+ }
2434
+ const isConfirmed = globalFlags.yes ? true : await confirm({
2435
+ message: `Would you like to proceed?`,
2436
+ active: "Install MCP",
2437
+ inactive: "Cancel"
2438
+ });
2439
+ if (isConfirmed !== true) {
2440
+ outro(chalk.bold.red("Installation cancelled"));
2441
+ process.exit(0);
2442
+ }
2443
+ const configContent = serializeClientConfig(
2444
+ clientFileTarget,
2445
+ config,
2446
+ content
2447
+ );
2448
+ fs__default.writeFileSync(clientFileTarget.path, configContent);
2449
+ log$1.success(chalk.bold.green(`Added x402scan MCP to ${name}`));
2450
+ } catch (e) {
2451
+ log$1.error(chalk.bold.red(`Error adding x402scan MCP to ${name}`));
2452
+ throw e;
2453
+ }
2454
+ }
2455
+ var getMcpConfig, formatDiffByFormat;
2456
+ var init_add_server = __esm({
2457
+ "src/install/2-add-server/index.ts"() {
2458
+ init_version();
2459
+ init_clients();
2460
+ init_lib2();
2461
+ init_log();
2462
+ init_wait();
2463
+ getMcpConfig = (globalFlags) => {
2464
+ if (globalFlags.dev) {
2465
+ return {
2466
+ serverName: "x402",
2467
+ command: "node",
2468
+ args: [`${process.cwd()}/dist/esm/index.js`, "--dev"]
2469
+ };
2470
+ }
2471
+ return {
2472
+ serverName: "x402",
2473
+ command: "npx",
2474
+ args: ["-y", `@x402scan/mcp@${DIST_TAG}`]
2475
+ };
2476
+ };
2477
+ formatDiffByFormat = (obj, format2) => {
2478
+ const str = stringifyObject(obj, format2);
2479
+ switch (format2) {
2480
+ case "json" /* JSON */: {
2481
+ const numLines = str.split("\n").length;
2482
+ return str.split("\n").map((line, index) => {
2483
+ const diffLines = [0, 1, numLines - 2, numLines - 1];
2484
+ const isDiffLine = !diffLines.includes(index);
2485
+ if (isDiffLine) {
2486
+ return `${chalk.bold.green(`+ ${line.slice(2)}`)}`;
2487
+ }
2488
+ return line;
2489
+ }).join("\n");
2490
+ }
2491
+ case "yaml" /* YAML */: {
2492
+ return str.split("\n").map((line, index) => {
2493
+ const diffLines = [0, 1, str.length - 2, str.length - 1];
2494
+ const isDiffLine = !diffLines.includes(index);
2495
+ if (isDiffLine) {
2496
+ return `${chalk.bold.green(`+ ${line.slice(2)}`)}`;
2497
+ }
2498
+ return line;
2499
+ }).join("\n");
2500
+ }
2501
+ case "toml" /* TOML */: {
2502
+ return str.split("\n").filter((line) => line.trim() !== "").map((line) => {
2503
+ return `${chalk.bold.green(`+ ${line.trim()}`)}`;
2504
+ }).join("\n");
2505
+ }
2506
+ }
2507
+ };
2508
+ }
2509
+ });
2510
+ var redeemInviteCode2;
2511
+ var init_redeem_invite3 = __esm({
2512
+ "src/install/3-redeem-invite/index.ts"() {
2513
+ init_wait();
2514
+ init_redeem_invite();
2515
+ redeemInviteCode2 = async (props, flags) => {
2516
+ const s = spinner();
2517
+ if (!flags.yes) {
2518
+ s.start("Redeeming invite code...");
2519
+ }
2520
+ const result = await redeemInviteCode(props);
2521
+ return result.match(
2522
+ async ({ data }) => {
2523
+ if (!flags.yes) {
2524
+ s.stop("Invite code redeemed successfully!");
2525
+ await wait({
2526
+ startText: "Processing...",
2527
+ stopText: chalk.green(
2528
+ `${chalk.bold(data.amount)} USDC has been sent to your wallet!`
2529
+ ),
2530
+ ms: 1e3
2531
+ });
2532
+ } else {
2533
+ log$1.success(
2534
+ chalk.green(
2535
+ `${chalk.bold(data.amount)} USDC has been sent to your wallet!`
2536
+ )
2537
+ );
2538
+ }
2539
+ log$1.info(
2540
+ chalk.dim(`Transaction: https://basescan.org/tx/${data.txHash}`)
2541
+ );
2542
+ return true;
2543
+ },
2544
+ (error) => {
2545
+ if (!flags.yes) {
2546
+ s.stop("Invite code redemption failed");
2547
+ }
2548
+ log$1.warning(
2549
+ chalk.yellow(`Failed to redeem invite code: ${error?.message}`)
2550
+ );
2551
+ return false;
2552
+ }
2553
+ );
2554
+ };
2555
+ }
2556
+ });
2557
+ var addFunds;
2558
+ var init_add_funds = __esm({
2559
+ "src/install/4-add-funds/index.ts"() {
2560
+ init_balance();
2561
+ init_deposit();
2562
+ init_wait();
2563
+ addFunds = async ({ flags, address, isNew }) => {
2564
+ if (isNew) {
2565
+ if (!flags.yes) {
2566
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2567
+ }
2568
+ log$1.info("To use paid API tools, you will need USDC in your wallet.");
2569
+ await promptDeposit(address, flags);
2570
+ } else {
2571
+ const { balanceFormatted } = await getUSDCBalance(address, flags);
2572
+ if (!flags.yes) {
2573
+ await wait({
2574
+ startText: "Checking balance...",
2575
+ stopText: `Balance: ${chalk.bold(`${balanceFormatted} USDC`)} `,
2576
+ ms: 1e3
2577
+ });
2578
+ }
2579
+ if (balanceFormatted < 1) {
2580
+ log$1.warning(
2581
+ chalk.bold(
2582
+ `Your balance is low (${balanceFormatted} USDC). Consider topping up.`
2583
+ )
2584
+ );
2585
+ await promptDeposit(address, flags);
2586
+ }
2587
+ }
2588
+ };
2589
+ }
2590
+ });
2591
+
2592
+ // src/install/index.ts
2593
+ var install_exports = {};
2594
+ __export(install_exports, {
2595
+ installMcpServer: () => installMcpServer
2596
+ });
2597
+ var installMcpServer;
2598
+ var init_install = __esm({
2599
+ "src/install/index.ts"() {
2600
+ init_wallet2();
2601
+ init_get_client();
2602
+ init_add_server();
2603
+ init_redeem_invite3();
2604
+ init_add_funds();
2605
+ installMcpServer = async (flags) => {
2606
+ const {
2607
+ account: { address },
2608
+ isNew
2609
+ } = await getWallet();
2610
+ intro(chalk.green.bold(`Install x402scan MCP`));
2611
+ const client = await getClient(flags);
2612
+ await addServer(client, flags);
2613
+ const inviteRedeemed = flags.invite ? await redeemInviteCode2(
2614
+ {
2615
+ code: flags.invite,
2616
+ dev: flags.dev,
2617
+ address
2618
+ },
2619
+ flags
2620
+ ) : false;
2621
+ if (!inviteRedeemed) {
2622
+ await addFunds({ flags, address, isNew });
2623
+ }
2624
+ outro(chalk.bold.green("Your x402scan MCP server is ready to use!"));
2625
+ };
2626
+ }
2627
+ });
2628
+
2629
+ // src/fund/index.ts
2630
+ var fund_exports = {};
2631
+ __export(fund_exports, {
2632
+ fundMcpServer: () => fundMcpServer
2633
+ });
2634
+ var fundMcpServer;
2635
+ var init_fund = __esm({
2636
+ "src/fund/index.ts"() {
2637
+ init_wallet2();
2638
+ init_deposit();
2639
+ fundMcpServer = async (flags) => {
2640
+ intro(chalk.bold(`Fund ${chalk.hex("#2563eb")("x402scan MCP")}`));
2641
+ const {
2642
+ account: { address }
2643
+ } = await getWallet();
2644
+ await promptDeposit(address, flags);
2645
+ outro(chalk.bold.green("Your x402scan MCP server is funded!"));
2646
+ };
2647
+ }
2648
+ });
3
2649
 
4
2650
  // src/index.ts
5
- import yargs from "yargs";
6
- import { hideBin } from "yargs/helpers";
2651
+ init_clients();
7
2652
  var isClaudeCode = Boolean(process.env.CLAUDECODE);
8
2653
  var defaultYes = isClaudeCode || Boolean(process.env.CI);
9
2654
  void yargs(hideBin(process.argv)).scriptName("@x402scan/mcp").option("dev", {
@@ -24,8 +2669,8 @@ void yargs(hideBin(process.argv)).scriptName("@x402scan/mcp").option("dev", {
24
2669
  "Start the MCP server",
25
2670
  (yargs2) => yargs2,
26
2671
  async (args) => {
27
- const { startServer } = await import("./server-IOVNYPTB.js");
28
- await startServer(args);
2672
+ const { startServer: startServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2673
+ await startServer2(args);
29
2674
  }
30
2675
  ).command(
31
2676
  "install",
@@ -37,19 +2682,20 @@ void yargs(hideBin(process.argv)).scriptName("@x402scan/mcp").option("dev", {
37
2682
  default: isClaudeCode ? "claude-code" /* ClaudeCode */ : void 0
38
2683
  }),
39
2684
  async (args) => {
40
- const { installMcpServer } = await import("./install-BBOI4D6I.js");
41
- await installMcpServer(args);
2685
+ const { installMcpServer: installMcpServer2 } = await Promise.resolve().then(() => (init_install(), install_exports));
2686
+ await installMcpServer2(args);
42
2687
  }
43
2688
  ).command(
44
2689
  "fund",
45
2690
  "Open the funding page",
46
2691
  (yargs2) => yargs2,
47
2692
  async (args) => {
48
- const { fundMcpServer } = await import("./fund-ANZCZU5C.js");
49
- await fundMcpServer(args);
2693
+ const { fundMcpServer: fundMcpServer2 } = await Promise.resolve().then(() => (init_fund(), fund_exports));
2694
+ await fundMcpServer2(args);
50
2695
  }
51
- ).strict().demandCommand(0, 1, "", "Too many commands provided").help().parseAsync().catch((err) => {
52
- console.error("Fatal:", err);
2696
+ ).strict().demandCommand(0, 1, "", "Too many commands provided").help().parseAsync().catch((err2) => {
2697
+ console.error("Fatal:", err2);
53
2698
  process.exit(1);
54
2699
  });
2700
+ //# sourceMappingURL=index.js.map
55
2701
  //# sourceMappingURL=index.js.map