@x402storage/mcp 1.0.1 → 1.0.2

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/config.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  /**
2
2
  * Environment validation for x402store MCP server
3
3
  */
4
+ export type WalletType = 'evm' | 'solana';
5
+ /**
6
+ * Detects wallet type from private key format
7
+ */
8
+ export declare function detectWalletType(key: string): WalletType;
4
9
  /**
5
10
  * Validates required environment variables.
6
11
  * Returns error message if X402_PRIVATE_KEY is missing, null if valid.
@@ -10,4 +15,16 @@ export declare function validateEnvironment(): string | null;
10
15
  * Gets the private key from environment.
11
16
  * Should only be called after validateEnvironment() returns null.
12
17
  */
13
- export declare function getPrivateKey(): `0x${string}`;
18
+ export declare function getPrivateKey(): string;
19
+ /**
20
+ * Wallet info returned by getWalletInfo
21
+ */
22
+ export interface WalletInfo {
23
+ address: string;
24
+ balance: string;
25
+ chain: string;
26
+ }
27
+ /**
28
+ * Gets wallet address and balance from the configured private key
29
+ */
30
+ export declare function getWalletInfo(): Promise<WalletInfo>;
package/dist/config.js CHANGED
@@ -1,13 +1,33 @@
1
1
  /**
2
2
  * Environment validation for x402store MCP server
3
3
  */
4
+ import { privateKeyToAccount } from 'viem/accounts';
5
+ import { createPublicClient, http, formatUnits } from 'viem';
6
+ import { base } from 'viem/chains';
7
+ import { Connection, Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js';
8
+ /**
9
+ * Detects wallet type from private key format
10
+ */
11
+ export function detectWalletType(key) {
12
+ const trimmed = key.trim();
13
+ // EVM keys start with 0x
14
+ if (trimmed.startsWith('0x')) {
15
+ return 'evm';
16
+ }
17
+ // Solana keys are JSON arrays
18
+ if (trimmed.startsWith('[')) {
19
+ return 'solana';
20
+ }
21
+ // Default to EVM for other formats
22
+ return 'evm';
23
+ }
4
24
  /**
5
25
  * Validates required environment variables.
6
26
  * Returns error message if X402_PRIVATE_KEY is missing, null if valid.
7
27
  */
8
28
  export function validateEnvironment() {
9
29
  if (!process.env.X402_PRIVATE_KEY) {
10
- return 'X402_PRIVATE_KEY not set. Export your Base wallet private key: export X402_PRIVATE_KEY=0x... Need a wallet? Create one at https://x402.storage';
30
+ return 'X402_PRIVATE_KEY not set. Run /x402storage:setup to configure.';
11
31
  }
12
32
  return null;
13
33
  }
@@ -18,3 +38,66 @@ export function validateEnvironment() {
18
38
  export function getPrivateKey() {
19
39
  return process.env.X402_PRIVATE_KEY;
20
40
  }
41
+ /**
42
+ * Gets wallet address and balance from the configured private key
43
+ */
44
+ export async function getWalletInfo() {
45
+ const privateKey = getPrivateKey();
46
+ const walletType = detectWalletType(privateKey);
47
+ if (walletType === 'solana') {
48
+ return getSolanaWalletInfo(privateKey);
49
+ }
50
+ else {
51
+ return getEvmWalletInfo(privateKey);
52
+ }
53
+ }
54
+ /**
55
+ * Gets Solana wallet info
56
+ */
57
+ async function getSolanaWalletInfo(privateKey) {
58
+ const secretKey = Uint8Array.from(JSON.parse(privateKey));
59
+ const keypair = Keypair.fromSecretKey(secretKey);
60
+ const address = keypair.publicKey.toBase58();
61
+ const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
62
+ const balance = await connection.getBalance(keypair.publicKey);
63
+ const solBalance = (balance / LAMPORTS_PER_SOL).toFixed(4);
64
+ return {
65
+ address,
66
+ balance: `${solBalance} SOL`,
67
+ chain: 'Solana',
68
+ };
69
+ }
70
+ /**
71
+ * Gets EVM wallet info (Base network)
72
+ */
73
+ async function getEvmWalletInfo(privateKey) {
74
+ const account = privateKeyToAccount(privateKey);
75
+ const client = createPublicClient({
76
+ chain: base,
77
+ transport: http(),
78
+ });
79
+ const ethBalance = await client.getBalance({ address: account.address });
80
+ // USDC contract on Base
81
+ const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
82
+ const usdcBalance = await client.readContract({
83
+ address: USDC_ADDRESS,
84
+ abi: [
85
+ {
86
+ name: 'balanceOf',
87
+ type: 'function',
88
+ stateMutability: 'view',
89
+ inputs: [{ name: 'account', type: 'address' }],
90
+ outputs: [{ name: '', type: 'uint256' }],
91
+ },
92
+ ],
93
+ functionName: 'balanceOf',
94
+ args: [account.address],
95
+ });
96
+ const ethFormatted = parseFloat(formatUnits(ethBalance, 18)).toFixed(4);
97
+ const usdcFormatted = parseFloat(formatUnits(usdcBalance, 6)).toFixed(2);
98
+ return {
99
+ address: account.address,
100
+ balance: `${usdcFormatted} USDC, ${ethFormatted} ETH`,
101
+ chain: 'Base',
102
+ };
103
+ }
package/dist/index.js CHANGED
@@ -3,8 +3,21 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { z } from 'zod';
5
5
  import { resolve } from 'node:path';
6
- import { validateEnvironment, getPrivateKey } from './config.js';
6
+ import { randomBytes } from 'node:crypto';
7
+ import { writeFileSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
9
+ import { privateKeyToAccount } from 'viem/accounts';
10
+ import { validateEnvironment, getPrivateKey, getWalletInfo } from './config.js';
7
11
  import { uploadFile, FileNotFoundError, UploadError } from './upload.js';
12
+ // Handle --generate-wallet flag before MCP server setup
13
+ if (process.argv.includes('--generate-wallet')) {
14
+ const privateKey = `0x${randomBytes(32).toString('hex')}`;
15
+ const walletPath = `${homedir()}/.x402-wallet`;
16
+ writeFileSync(walletPath, privateKey, { mode: 0o600 });
17
+ const account = privateKeyToAccount(privateKey);
18
+ console.log(account.address);
19
+ process.exit(0);
20
+ }
8
21
  // Create MCP server
9
22
  const server = new McpServer({
10
23
  name: 'x402store',
@@ -70,6 +83,32 @@ server.tool('store_file', 'Store a file permanently on IPFS via x402.storage. Re
70
83
  };
71
84
  }
72
85
  });
86
+ // Register wallet tool
87
+ server.tool('wallet', 'Show your x402.storage wallet address and balance', {}, async () => {
88
+ const envError = validateEnvironment();
89
+ if (envError) {
90
+ return {
91
+ content: [{ type: 'text', text: `Error: ${envError}` }],
92
+ };
93
+ }
94
+ try {
95
+ const info = await getWalletInfo();
96
+ return {
97
+ content: [
98
+ {
99
+ type: 'text',
100
+ text: `Address: ${info.address}\nBalance: ${info.balance}`,
101
+ },
102
+ ],
103
+ };
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : 'Unknown error';
107
+ return {
108
+ content: [{ type: 'text', text: `Error: ${message}` }],
109
+ };
110
+ }
111
+ });
73
112
  // Run server with stdio transport
74
113
  async function main() {
75
114
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x402storage/mcp",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server for x402.storage file uploads",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,9 +30,11 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "^1.25.0",
33
+ "@solana/web3.js": "^1.98.4",
33
34
  "@x402/core": "^2.2.0",
34
35
  "@x402/evm": "latest",
35
36
  "@x402/fetch": "latest",
37
+ "bs58": "^6.0.0",
36
38
  "viem": "^2.21.0",
37
39
  "zod": "^3.24.0"
38
40
  },