@x402scan/mcp 0.0.7-beta.1 → 0.0.7-beta.3

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