@x402storage/mcp 1.0.1 → 1.0.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/config.d.ts +18 -1
- package/dist/config.js +84 -1
- package/dist/index.js +40 -1
- package/package.json +4 -1
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():
|
|
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.
|
|
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 {
|
|
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.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "MCP server for x402.storage file uploads",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"url": "https://github.com/rawgroundbeef/x402.storage"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
+
"mcp": "./dist/index.js",
|
|
12
13
|
"x402-mcp": "./dist/index.js"
|
|
13
14
|
},
|
|
14
15
|
"files": [
|
|
@@ -30,9 +31,11 @@
|
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"@modelcontextprotocol/sdk": "^1.25.0",
|
|
34
|
+
"@solana/web3.js": "^1.98.4",
|
|
33
35
|
"@x402/core": "^2.2.0",
|
|
34
36
|
"@x402/evm": "latest",
|
|
35
37
|
"@x402/fetch": "latest",
|
|
38
|
+
"bs58": "^6.0.0",
|
|
36
39
|
"viem": "^2.21.0",
|
|
37
40
|
"zod": "^3.24.0"
|
|
38
41
|
},
|