Skip to content

Commit 4b72854

Browse files
committed
Merge branch 'main' of github.com:sei-protocol/sei-js into feature/mintlify
2 parents d92f163 + 311d09b commit 4b72854

29 files changed

Lines changed: 1417 additions & 532 deletions

.changeset/some-areas-fail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sei-js/mcp-server": patch
3+
---
4+
5+
Disable wallet based tools by default, add ability to add more wallet providers

packages/create-sei/biome.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3-
"extends": ["../../biome.json"],
4-
"files": {
5-
"ignoreUnknown": false,
6-
"ignore": ["templates/**"]
7-
}
8-
}
2+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3+
"extends": ["../../biome.json"],
4+
"files": {
5+
"ignoreUnknown": false,
6+
"ignore": ["templates/**"]
7+
}
8+
}

packages/ledger/package.json

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
"module": "./dist/esm/src/index.js",
77
"types": "./dist/types/src/index.d.ts",
88
"sideEffects": false,
9-
"files": [
10-
"dist"
11-
],
9+
"files": ["dist"],
1210
"scripts": {
1311
"build": "rimraf dist && yarn build:cjs && yarn build:esm && yarn build:types",
1412
"build:cjs": "tsc --outDir dist/cjs --module commonjs",
@@ -18,12 +16,7 @@
1816
"test": "jest"
1917
},
2018
"homepage": "https://github.com/sei-protocol/sei-js#readme",
21-
"keywords": [
22-
"sei",
23-
"javascript",
24-
"typescript",
25-
"ledger"
26-
],
19+
"keywords": ["sei", "javascript", "typescript", "ledger"],
2720
"repository": "git@github.com:sei-protocol/sei-js.git",
2821
"license": "MIT",
2922
"publishConfig": {

packages/mcp-server/.env.example

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
# Sei MCP Server Environment Variables
22

3+
# Wallet Configuration
4+
# Wallet mode: private-key | dynamic | porto | disabled
5+
# - disabled: Disable all wallet functionality (default - safest for production)
6+
# - private-key: Use PRIVATE_KEY environment variable
7+
WALLET_MODE=disabled
8+
39
# Private key for blockchain transactions (without 0x prefix)
4-
# This is used when no private key is provided in the request
10+
# Used when WALLET_MODE=private-key
511
# SECURITY: Never commit your actual private key to version control
612
PRIVATE_KEY=your_private_key_here
13+
14+
# Wallet API Key (future use with wallet providers)
15+
# WALLET_API_KEY=your_wallet_api_key_here

packages/mcp-server/bin/cli.js

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#!/usr/bin/env node
22

3+
import { fileURLToPath } from 'node:url';
4+
import { dirname, resolve } from 'node:path';
35
import { spawn } from 'node:child_process';
46
import { createRequire } from 'node:module';
5-
import { dirname, resolve } from 'node:path';
6-
import { fileURLToPath } from 'node:url';
77

88
const __filename = fileURLToPath(import.meta.url);
99
const __dirname = dirname(__filename);
@@ -13,37 +13,60 @@ const require = createRequire(import.meta.url);
1313
const args = process.argv.slice(2);
1414
const httpMode = args.includes('--http') || args.includes('-h');
1515

16+
// Parse wallet mode argument
17+
let walletMode = null;
18+
const walletModeIndex = args.findIndex(arg => arg === '--wallet-mode');
19+
if (walletModeIndex !== -1 && walletModeIndex + 1 < args.length) {
20+
walletMode = args[walletModeIndex + 1];
21+
}
22+
23+
// Set environment variables based on CLI arguments
24+
if (walletMode) {
25+
const validModes = ['private-key', 'disabled'];
26+
if (validModes.includes(walletMode)) {
27+
process.env.WALLET_MODE = walletMode;
28+
} else {
29+
console.error(`Invalid wallet mode: ${walletMode}. Valid modes are: ${validModes.join(', ')}`);
30+
process.exit(1);
31+
}
32+
}
33+
1634
// Determine which file to execute
1735
const scriptPath = resolve(__dirname, '../dist/esm', httpMode ? '/server/http-server.js' : 'index.js');
1836

1937
try {
20-
// Check if the built files exist
21-
require.resolve(scriptPath);
22-
23-
// Execute the server
24-
const server = spawn('node', [scriptPath], {
25-
stdio: 'inherit',
26-
shell: false
27-
});
28-
29-
server.on('error', (err) => {
30-
console.error('Failed to start server:', err);
31-
process.exit(1);
32-
});
33-
34-
// Handle clean shutdown
35-
const cleanup = () => {
36-
if (!server.killed) {
37-
server.kill();
38-
}
39-
};
40-
41-
process.on('SIGINT', cleanup);
42-
process.on('SIGTERM', cleanup);
43-
process.on('exit', cleanup);
38+
// Check if the built files exist
39+
require.resolve(scriptPath);
40+
41+
// Execute the server
42+
const server = spawn('node', [scriptPath], {
43+
stdio: 'inherit',
44+
shell: false
45+
});
46+
47+
server.on('error', (err) => {
48+
console.error('Failed to start server:', err);
49+
process.exit(1);
50+
});
51+
52+
// Handle clean shutdown
53+
const cleanup = () => {
54+
if (!server.killed) {
55+
server.kill();
56+
}
57+
};
58+
59+
process.on('SIGINT', cleanup);
60+
process.on('SIGTERM', cleanup);
61+
process.on('exit', cleanup);
62+
4463
} catch (error) {
45-
console.error('Error: Server files not found. The package may not be built correctly.');
46-
console.error('Please try reinstalling the package or contact the maintainers.');
47-
console.error(error);
48-
process.exit(1);
49-
}
64+
console.error('Error: Server files not found. The package may not be built correctly.');
65+
console.error('Please try reinstalling the package or contact the maintainers.');
66+
console.error('\nUsage:');
67+
console.error(' mcp-server # Start in STDIO mode (default)');
68+
console.error(' mcp-server --http # Start in HTTP mode');
69+
console.error(' mcp-server --wallet-mode MODE # Set wallet mode (private-key|dynamic|porto|disabled)');
70+
console.error(error);
71+
process.exit(1);
72+
}

packages/mcp-server/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
},
2626
"dependencies": {
2727
"@modelcontextprotocol/sdk": "^1.7.0",
28-
"axios": "^1.9.0",
2928
"cors": "^2.8.5",
3029
"dotenv": "^16.5.0",
3130
"express": "^4.21.2",
32-
"trieve-ts-sdk": "^0.0.118",
31+
"jest": "^30.0.3",
32+
"tsx": "^4.20.3",
3333
"viem": "^2.30.5",
3434
"zod": "^3.24.2"
3535
},

packages/mcp-server/src/core/config.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import { z } from 'zod';
55
// Load environment variables from .env file
66
dotenv.config();
77

8+
// Wallet mode types
9+
export type WalletMode = 'private-key' | 'disabled';
10+
811
// Define environment variable schema
912
const envSchema = z.object({
10-
PRIVATE_KEY: z.string().optional()
13+
PRIVATE_KEY: z.string().optional(),
14+
WALLET_MODE: z.enum(['private-key', 'disabled']).default('disabled'),
15+
WALLET_API_KEY: z.string().optional() // Used for wallet providers
1116
});
1217

1318
// Parse and validate environment variables
@@ -23,7 +28,9 @@ export const formatPrivateKey = (key?: string): string | undefined => {
2328

2429
// Export validated environment variables with formatted private key
2530
export const config = {
26-
privateKey: env.success ? formatPrivateKey(env.data.PRIVATE_KEY) : undefined
31+
privateKey: env.success ? formatPrivateKey(env.data.PRIVATE_KEY) : undefined,
32+
walletMode: (env.success ? env.data.WALLET_MODE : 'disabled') as WalletMode,
33+
walletApiKey: env.success ? env.data.WALLET_API_KEY : undefined
2734
};
2835

2936
/**
@@ -34,3 +41,19 @@ export const config = {
3441
export function getPrivateKeyAsHex(): Hex | undefined {
3542
return config.privateKey as Hex | undefined;
3643
}
44+
45+
/**
46+
* Check if wallet functionality is enabled based on configuration
47+
* @returns True if wallet functionality should be available
48+
*/
49+
export function isWalletEnabled(): boolean {
50+
return config.walletMode !== 'disabled';
51+
}
52+
53+
/**
54+
* Get the current wallet mode
55+
* @returns The configured wallet mode
56+
*/
57+
export function getWalletMode(): WalletMode {
58+
return config.walletMode;
59+
}

packages/mcp-server/src/core/prompts.ts

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
22
import { z } from 'zod';
33
import { DEFAULT_NETWORK } from './chains.js';
4+
import { isWalletEnabled } from './config.js';
45

56
/**
67
* Register all EVM-related prompts with the MCP server
78
* @param server The MCP server instance
89
*/
910
export function registerEVMPrompts(server: McpServer) {
11+
// Register read-only prompts (always available)
12+
registerReadOnlyPrompts(server);
13+
14+
// Register wallet-dependent prompts (only if wallet is enabled)
15+
if (isWalletEnabled()) {
16+
registerWalletPrompts(server);
17+
} else {
18+
console.error('Wallet functionality is disabled. Wallet-dependent prompts will not be available.');
19+
}
20+
}
21+
22+
/**
23+
* Register read-only prompts that don't require wallet functionality
24+
* @param server The MCP server instance
25+
*/
26+
function registerReadOnlyPrompts(server: McpServer) {
1027
// Basic block explorer prompt
1128
server.prompt(
1229
'explore_block',
@@ -57,18 +74,7 @@ export function registerEVMPrompts(server: McpServer) {
5774
})
5875
);
5976

60-
// Get wallet address from private key prompt
61-
server.prompt('my_wallet_address', 'What is my wallet EVM address', {}, () => ({
62-
messages: [
63-
{
64-
role: 'user',
65-
content: {
66-
type: 'text',
67-
text: 'Please retrieve my wallet EVM address using tools get_address_from_private_key via MCP server.'
68-
}
69-
}
70-
]
71-
}));
77+
7278

7379
// Address analysis prompt
7480
server.prompt(
@@ -199,3 +205,67 @@ export function registerEVMPrompts(server: McpServer) {
199205
}
200206
);
201207
}
208+
209+
/**
210+
* Register wallet-dependent prompts that require wallet functionality
211+
* @param server The MCP server instance
212+
*/
213+
function registerWalletPrompts(server: McpServer) {
214+
// Get wallet address from private key prompt
215+
server.prompt('my_wallet_address', 'What is my wallet EVM address', {}, () => ({
216+
messages: [
217+
{
218+
role: 'user',
219+
content: {
220+
type: 'text',
221+
text: 'Please retrieve my wallet EVM address using tools get_address_from_private_key via MCP server.'
222+
}
223+
}
224+
]
225+
}));
226+
227+
// Send transaction prompt
228+
server.prompt(
229+
'send_transaction_guidance',
230+
'Get guidance on sending a transaction',
231+
{
232+
toAddress: z.string().describe('The recipient address'),
233+
amount: z.string().describe('The amount to send (in SEI)'),
234+
network: z.string().optional().describe('Network name or chain ID. Defaults to Sei mainnet.')
235+
},
236+
({ toAddress, amount, network = DEFAULT_NETWORK }) => ({
237+
messages: [
238+
{
239+
role: 'user',
240+
content: {
241+
type: 'text',
242+
text: `I want to send ${amount} SEI to ${toAddress} on the ${network} network. Please guide me through this process, including checking my balance first, estimating gas, and executing the transaction safely.`
243+
}
244+
}
245+
]
246+
})
247+
);
248+
249+
// Token transfer guidance
250+
server.prompt(
251+
'token_transfer_guidance',
252+
'Get guidance on transferring tokens',
253+
{
254+
tokenAddress: z.string().describe('The token contract address'),
255+
toAddress: z.string().describe('The recipient address'),
256+
amount: z.string().describe('The amount to transfer'),
257+
network: z.string().optional().describe('Network name or chain ID. Defaults to Sei mainnet.')
258+
},
259+
({ tokenAddress, toAddress, amount, network = DEFAULT_NETWORK }) => ({
260+
messages: [
261+
{
262+
role: 'user',
263+
content: {
264+
type: 'text',
265+
text: `I want to transfer ${amount} tokens from contract ${tokenAddress} to ${toAddress} on the ${network} network. Please guide me through this process, including checking my balance first, approving the token if needed, and executing the transfer safely.`
266+
}
267+
}
268+
]
269+
})
270+
);
271+
}

packages/mcp-server/src/core/services/clients.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { http, type Address, type Hex, type PublicClient, type WalletClient, createPublicClient, createWalletClient } from 'viem';
22
import { privateKeyToAccount } from 'viem/accounts';
33
import { DEFAULT_NETWORK, getChain, getRpcUrl } from '../chains.js';
4+
import { getWalletProvider } from '../wallet/index.js';
45

56
// Cache for clients to avoid recreating them for each request
67
const clientCache = new Map<string, PublicClient>();
@@ -37,26 +38,17 @@ export function getPublicClient(network = DEFAULT_NETWORK): PublicClient {
3738
}
3839

3940
/**
40-
* Create a wallet client for a specific network and private key
41+
* Get a wallet client using the configured wallet provider
4142
*/
42-
export function getWalletClient(privateKey: Hex, network = DEFAULT_NETWORK): WalletClient {
43-
const chain = getChain(network);
44-
const rpcUrl = getRpcUrl(network);
45-
const account = privateKeyToAccount(privateKey);
46-
47-
return createWalletClient({
48-
account,
49-
chain,
50-
transport: http(rpcUrl)
51-
});
43+
export async function getWalletClientFromProvider(network = DEFAULT_NETWORK): Promise<WalletClient> {
44+
const walletProvider = getWalletProvider();
45+
return walletProvider.getWalletClient(network);
5246
}
5347

5448
/**
55-
* Get an EVM address from a private key
56-
* @param privateKey The private key in hex format (with or without 0x prefix)
57-
* @returns The EVM address derived from the private key
49+
* Get an EVM address from the configured wallet provider
5850
*/
59-
export function getAddressFromPrivateKey(privateKey: Hex): Address {
60-
const account = privateKeyToAccount(privateKey);
61-
return account.address;
51+
export async function getAddressFromProvider(): Promise<Address> {
52+
const walletProvider = getWalletProvider();
53+
return walletProvider.getAddress();
6254
}

0 commit comments

Comments
 (0)