helius-mcp 0.5.0 → 0.5.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/README.md CHANGED
@@ -13,13 +13,15 @@ Set your API key:
13
13
  export HELIUS_API_KEY=your-api-key
14
14
  ```
15
15
 
16
- ## Tools (29)
16
+ ## Tools (48)
17
+
18
+ **Config (2):** setHeliusApiKey, getHeliusApiKeyStatus
17
19
 
18
20
  **DAS API (12):** getAsset, getAssetBatch, getAssetsByOwner, getAssetsByGroup, getAssetsByCreator, getAssetsByAuthority, searchAssets, getAssetProof, getAssetProofBatch, getSignaturesForAsset, getNftEditions, getTokenAccounts
19
21
 
20
- **RPC (4):** getBalance, getAccountInfo, getMultipleAccounts, getSignaturesForAddress
22
+ **RPC (7):** getBalance, getTokenBalances, getAccountInfo, getProgramAccounts, getNetworkStatus, getBlock, getTokenHolders
21
23
 
22
- **Transactions (1):** parseTransactions
24
+ **Transactions (2):** parseTransactions, getTransactionHistory
23
25
 
24
26
  **Priority Fees (1):** getPriorityFeeEstimate
25
27
 
@@ -29,11 +31,23 @@ export HELIUS_API_KEY=your-api-key
29
31
 
30
32
  **Laserstream gRPC (2):** laserstreamSubscribe, getLaserstreamInfo
31
33
 
32
- **Config (1):** setHeliusApiKey
34
+ **Wallet API (6):** getWalletIdentity, batchWalletIdentity, getWalletBalances, getWalletHistory, getWalletTransfers, getWalletFundedBy
35
+
36
+ **Plans & Guides (8):** getHeliusPlanInfo, compareHeliusPlans, getRateLimitInfo, getSenderInfo, getWebhookGuide, troubleshootError, getLatencyComparison, getPumpFunGuide
37
+
38
+ **Documentation (3):** lookupHeliusDocs, listHeliusDocTopics, getHeliusCreditsInfo
33
39
 
34
40
  ## Networks
35
41
 
36
- Mainnet Beta and Devnet. Set via `HELIUS_NETWORK` env var.
42
+ Mainnet and Devnet. Set via `HELIUS_NETWORK` env var or use the `network` parameter in `setHeliusApiKey`.
43
+
44
+ ## Development
45
+
46
+ ```bash
47
+ pnpm install
48
+ pnpm build
49
+ pnpm test
50
+ ```
37
51
 
38
52
  ## Docs
39
53
 
@@ -10,8 +10,8 @@ export function registerConfigTools(server) {
10
10
  content: [{
11
11
  type: 'text',
12
12
  text: fromEnv
13
- ? 'API key is configured via environment variable. Ready to use all Helius tools!'
14
- : 'API key is configured for this session. Ready to use all Helius tools!'
13
+ ? 'API key is configured via environment variable. Ready to use all Helius tools.'
14
+ : 'API key is configured for this session. Ready to use all Helius tools.'
15
15
  }]
16
16
  };
17
17
  }
@@ -19,7 +19,7 @@ export function registerConfigTools(server) {
19
19
  content: [{
20
20
  type: 'text',
21
21
  text: [
22
- '⚠️ No Helius API key configured.',
22
+ 'No Helius API key configured.',
23
23
  '',
24
24
  'To use Helius data tools, you need to set an API key:',
25
25
  '',
@@ -44,7 +44,7 @@ export function registerConfigTools(server) {
44
44
  });
45
45
  server.tool('setHeliusApiKey', 'Set the Helius API key for the current session. Required before using data tools (getBalance, getAsset, etc.). Get your free API key at https://dashboard.helius.dev/api-keys', {
46
46
  apiKey: z.string().describe('Your Helius API key from https://dashboard.helius.dev/api-keys'),
47
- network: z.enum(['mainnet-beta', 'devnet']).optional().default('mainnet-beta').describe('Network to use (default: mainnet-beta)')
47
+ network: z.enum(['mainnet', 'devnet']).optional().default('mainnet').describe('Network to use (default: mainnet)')
48
48
  }, async ({ apiKey, network }) => {
49
49
  setApiKey(apiKey);
50
50
  if (network) {
@@ -63,7 +63,7 @@ export function registerConfigTools(server) {
63
63
  content: [{
64
64
  type: 'text',
65
65
  text: [
66
- 'Invalid API key. The key was rejected by the Helius API.',
66
+ 'Invalid API key. The key was rejected by the Helius API.',
67
67
  '',
68
68
  'Please check your key and try again.',
69
69
  '',
@@ -78,7 +78,11 @@ export function registerConfigTools(server) {
78
78
  content: [{
79
79
  type: 'text',
80
80
  text: [
81
- `✅ Helius API key configured for ${network}!`,
81
+ `Helius API key configured. (default network: ${network})`,
82
+ '',
83
+ 'Your API key works for both mainnet and devnet. To switch networks:',
84
+ '- mainnet: https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',
85
+ '- devnet: https://devnet.helius-rpc.com/?api-key=YOUR_KEY',
82
86
  '',
83
87
  'You can now use all Helius tools:',
84
88
  '- getBalance, getTokenBalances - Check wallet balances',
@@ -296,8 +296,8 @@ export function registerGuideTools(server) {
296
296
  '',
297
297
  '| Feature | Helius Sender | Direct Jito |',
298
298
  '|---------|---------------|-------------|',
299
- '| SWQoS | Included | No |',
300
- '| Jito Bundles | Auto-bundled | Manual |',
299
+ '| SWQoS | Included | No |',
300
+ '| Jito Bundles | Auto-bundled | Manual |',
301
301
  '| Tips | Helius handles | You manage |',
302
302
  '| Setup | Use Helius RPC | Separate integration |',
303
303
  '',
@@ -126,18 +126,18 @@ function formatPlanDetails(planKey) {
126
126
  `- Enhanced WebSocket Connections: ${plan.connections.enhancedWebsocket}`,
127
127
  '',
128
128
  '### Features',
129
- `- Webhooks: ${plan.features.webhooks ? '' : ''}`,
130
- `- Standard WebSockets: ${plan.features.standardWebSockets ? '' : ''}`,
131
- `- Enhanced WebSockets: ${typeof plan.features.enhancedWebSockets === 'string' ? plan.features.enhancedWebSockets : plan.features.enhancedWebSockets ? '' : ''}`,
132
- `- Laserstream: ${typeof plan.features.laserstream === 'string' ? plan.features.laserstream : plan.features.laserstream ? '' : ''}`,
133
- `- Staked Connections: ${plan.features.stakedConnections ? '' : ''}`,
134
- `- Archival Data: ${plan.features.archivalData ? '' : ''}`,
129
+ `- Webhooks: ${plan.features.webhooks ? 'Yes' : 'No'}`,
130
+ `- Standard WebSockets: ${plan.features.standardWebSockets ? 'Yes' : 'No'}`,
131
+ `- Enhanced WebSockets: ${typeof plan.features.enhancedWebSockets === 'string' ? plan.features.enhancedWebSockets : plan.features.enhancedWebSockets ? 'Yes' : 'No'}`,
132
+ `- Laserstream: ${typeof plan.features.laserstream === 'string' ? plan.features.laserstream : plan.features.laserstream ? 'Yes' : 'No'}`,
133
+ `- Staked Connections: ${plan.features.stakedConnections ? 'Yes' : 'No'}`,
134
+ `- Archival Data: ${plan.features.archivalData ? 'Yes' : 'No'}`,
135
135
  ];
136
136
  if ('soc2Compliance' in plan.features) {
137
- lines.push(`- SOC 2 Compliance: ✅`);
137
+ lines.push(`- SOC 2 Compliance: Yes`);
138
138
  }
139
139
  if ('customInfrastructure' in plan.features) {
140
- lines.push(`- Custom Infrastructure: ✅`);
140
+ lines.push(`- Custom Infrastructure: Yes`);
141
141
  }
142
142
  lines.push('', '### Support');
143
143
  lines.push(`- Channel: ${plan.support}`);
@@ -161,8 +161,8 @@ export function registerPlanTools(server) {
161
161
  '| **sendTransaction** | 1/s | 5/s | 50/s | 100/s |',
162
162
  '| **DAS Requests** | 2/s | 10/s | 50/s | 100/s |',
163
163
  '| **WS Connections** | 5 | 150 | 250 | 250 |',
164
- '| **Enhanced WS** | | | (100) | (100) |',
165
- '| **Laserstream** | | Devnet | Devnet | Full |',
164
+ '| **Enhanced WS** | No | No | Yes (100) | Yes (100) |',
165
+ '| **Laserstream** | No | Devnet | Devnet | Full |',
166
166
  '| **Support SLA** | — | 24hr | 12hr | 8hr |',
167
167
  '',
168
168
  '---',
@@ -231,9 +231,9 @@ export function registerPlanTools(server) {
231
231
  lines.push('|------|-------------|-------------|--------|----------|');
232
232
  for (const p of plansToCompare) {
233
233
  const plan = HELIUS_PLANS[p];
234
- const ews = typeof plan.features.enhancedWebSockets === 'string' ? plan.features.enhancedWebSockets : plan.features.enhancedWebSockets ? '' : '';
235
- const ls = typeof plan.features.laserstream === 'string' ? plan.features.laserstream : plan.features.laserstream ? '' : '';
236
- lines.push(`| ${plan.name} | ${ews} | ${ls} | | |`);
234
+ const ews = typeof plan.features.enhancedWebSockets === 'string' ? plan.features.enhancedWebSockets : plan.features.enhancedWebSockets ? 'Yes' : 'No';
235
+ const ls = typeof plan.features.laserstream === 'string' ? plan.features.laserstream : plan.features.laserstream ? 'Yes' : 'No';
236
+ lines.push(`| ${plan.name} | ${ews} | ${ls} | Yes | Yes |`);
237
237
  }
238
238
  break;
239
239
  case 'connections':
@@ -212,7 +212,7 @@ export function registerTransactionTools(server) {
212
212
  const feeDisplay = tx.fee
213
213
  ? `${formatSol(tx.fee)} (${tx.fee.toLocaleString()} lamports)`
214
214
  : 'N/A';
215
- outputLines.push(`**Transaction: ${tx.signature}**`, '', `**Type:** ${tx.type || 'UNKNOWN'}`, `**Source:** ${tx.source || 'N/A'}`, `**Fee:** ${feeDisplay}`, `**Fee Payer:** ${tx.feePayer || 'N/A'}`, `**Timestamp:** ${tx.timestamp ? formatTimestamp(tx.timestamp) : 'N/A'}`, `**Status:** ${tx.transactionError ? 'Failed' : 'Success'}`);
215
+ outputLines.push(`**Transaction: ${tx.signature}**`, '', `**Type:** ${tx.type || 'UNKNOWN'}`, `**Source:** ${tx.source || 'N/A'}`, `**Fee:** ${feeDisplay}`, `**Fee Payer:** ${tx.feePayer || 'N/A'}`, `**Timestamp:** ${tx.timestamp ? formatTimestamp(tx.timestamp) : 'N/A'}`, `**Status:** ${tx.transactionError ? 'Failed' : 'Success'}`);
216
216
  // Show error details for failed transactions
217
217
  if (tx.transactionError) {
218
218
  let errDetail;
@@ -442,7 +442,7 @@ export function registerTransactionTools(server) {
442
442
  }
443
443
  const lines = [`**Signatures for ${formatAddress(address)}** (${sigs.length} results, newest first${statusNote})`, ''];
444
444
  sigs.forEach((sig) => {
445
- const sigStatus = sig.err ? '' : '';
445
+ const sigStatus = sig.err ? '[FAILED]' : '[OK]';
446
446
  const time = sig.blockTime ? new Date(sig.blockTime * 1000).toISOString() : 'N/A';
447
447
  lines.push(`${sigStatus} ${sig.signature}`);
448
448
  lines.push(` Slot: ${sig.slot.toLocaleString()} | Time: ${time}`);
@@ -495,7 +495,7 @@ export function registerTransactionTools(server) {
495
495
  const orderLabel = sortOrder === 'asc' ? 'oldest first' : 'newest first';
496
496
  const lines = [`**Signatures for ${formatAddress(address)}** (${items.length} results, ${orderLabel}${statusNote})`, ''];
497
497
  items.forEach((item) => {
498
- const txStatus = item.err ? '' : '';
498
+ const txStatus = item.err ? '[FAILED]' : '[OK]';
499
499
  const time = item.blockTime ? new Date(item.blockTime * 1000).toISOString() : 'N/A';
500
500
  lines.push(`${txStatus} ${item.signature}`);
501
501
  lines.push(` Slot: ${item.slot.toLocaleString()} | Time: ${time}`);
@@ -544,7 +544,7 @@ export function registerTransactionTools(server) {
544
544
  if (transactionDetails === 'signatures') {
545
545
  const items = result.data;
546
546
  items.forEach((item) => {
547
- const txStatus = item.err ? '' : '';
547
+ const txStatus = item.err ? '[FAILED]' : '[OK]';
548
548
  const time = item.blockTime ? new Date(item.blockTime * 1000).toISOString() : 'N/A';
549
549
  lines.push(`${txStatus} ${item.signature}`);
550
550
  lines.push(` Slot: ${item.slot.toLocaleString()} | Index: ${item.transactionIndex} | Time: ${time}`);
@@ -557,7 +557,7 @@ export function registerTransactionTools(server) {
557
557
  const items = result.data;
558
558
  items.forEach((item) => {
559
559
  const sig = item.transaction.signatures[0];
560
- const txStatus = item.meta.err ? '' : '';
560
+ const txStatus = item.meta.err ? '[FAILED]' : '[OK]';
561
561
  const time = item.blockTime ? new Date(item.blockTime * 1000).toISOString() : 'N/A';
562
562
  const fee = formatSol(item.meta.fee);
563
563
  lines.push(`${txStatus} ${sig}`);
@@ -643,7 +643,7 @@ export function registerTransactionTools(server) {
643
643
  const lines = [`**Transaction History for ${formatAddress(address)}** (${allTransactions.length} transactions, ${orderLabel}${statusNote})`, ''];
644
644
  allTransactions.forEach((tx) => {
645
645
  const time = tx.timestamp ? formatTimestamp(tx.timestamp) : 'N/A';
646
- const txStatus = tx.transactionError ? '' : '';
646
+ const txStatus = tx.transactionError ? '[FAILED]' : '[OK]';
647
647
  const type = tx.type || 'UNKNOWN';
648
648
  const source = tx.source || '';
649
649
  lines.push(`${txStatus} **${type}**${source ? ` (${source})` : ''} - ${time}`);
@@ -28,7 +28,7 @@ export function registerWebhookTools(server) {
28
28
  catch (err) {
29
29
  const errorMsg = err instanceof Error ? err.message : String(err);
30
30
  return {
31
- content: [{ type: 'text', text: `❌ Error: ${errorMsg}` }],
31
+ content: [{ type: 'text', text: `Error: ${errorMsg}` }],
32
32
  isError: true
33
33
  };
34
34
  }
@@ -61,7 +61,7 @@ export function registerWebhookTools(server) {
61
61
  catch (err) {
62
62
  const errorMsg = err instanceof Error ? err.message : String(err);
63
63
  return {
64
- content: [{ type: 'text', text: `❌ Error: ${errorMsg}` }],
64
+ content: [{ type: 'text', text: `Error: ${errorMsg}` }],
65
65
  isError: true
66
66
  };
67
67
  }
@@ -86,14 +86,14 @@ export function registerWebhookTools(server) {
86
86
  return {
87
87
  content: [{
88
88
  type: 'text',
89
- text: `✅ **Webhook Created**\n\n**ID:** ${webhook.webhookID}\n**URL:** ${webhook.webhookURL}\n**Monitoring:** ${accountAddresses.length} address(es)`
89
+ text: `**Webhook Created**\n\n**ID:** ${webhook.webhookID}\n**URL:** ${webhook.webhookURL}\n**Monitoring:** ${accountAddresses.length} address(es)`
90
90
  }]
91
91
  };
92
92
  }
93
93
  catch (err) {
94
94
  const errorMsg = err instanceof Error ? err.message : String(err);
95
95
  return {
96
- content: [{ type: 'text', text: `❌ Error: ${errorMsg}` }],
96
+ content: [{ type: 'text', text: `Error: ${errorMsg}` }],
97
97
  isError: true
98
98
  };
99
99
  }
@@ -127,14 +127,14 @@ export function registerWebhookTools(server) {
127
127
  return {
128
128
  content: [{
129
129
  type: 'text',
130
- text: `✅ **Webhook Updated**\n\n**ID:** ${webhook.webhookID}\n**URL:** ${webhook.webhookURL}`
130
+ text: `**Webhook Updated**\n\n**ID:** ${webhook.webhookID}\n**URL:** ${webhook.webhookURL}`
131
131
  }]
132
132
  };
133
133
  }
134
134
  catch (err) {
135
135
  const errorMsg = err instanceof Error ? err.message : String(err);
136
136
  return {
137
- content: [{ type: 'text', text: `❌ Error: ${errorMsg}` }],
137
+ content: [{ type: 'text', text: `Error: ${errorMsg}` }],
138
138
  isError: true
139
139
  };
140
140
  }
@@ -149,14 +149,14 @@ export function registerWebhookTools(server) {
149
149
  return {
150
150
  content: [{
151
151
  type: 'text',
152
- text: `✅ Webhook ${webhookID} deleted successfully.`
152
+ text: `Webhook ${webhookID} deleted successfully.`
153
153
  }]
154
154
  };
155
155
  }
156
156
  catch (err) {
157
157
  const errorMsg = err instanceof Error ? err.message : String(err);
158
158
  return {
159
- content: [{ type: 'text', text: `❌ Error: ${errorMsg}` }],
159
+ content: [{ type: 'text', text: `Error: ${errorMsg}` }],
160
160
  isError: true
161
161
  };
162
162
  }
@@ -4,3 +4,4 @@ export declare function formatAddress(address: string): string;
4
4
  export declare function formatTimestamp(unixTime: number): string;
5
5
  export declare function formatTokenAmount(amount: number, decimals: number): string;
6
6
  export declare function formatSolCompact(lamports: number): string;
7
+ export declare function getOrbExplorerUrl(addressOrSignature: string, type?: 'address' | 'tx'): string;
@@ -18,3 +18,6 @@ export function formatTokenAmount(amount, decimals) {
18
18
  export function formatSolCompact(lamports) {
19
19
  return `${(lamports / LAMPORTS_PER_SOL).toLocaleString(undefined, { maximumFractionDigits: 0 })} SOL`;
20
20
  }
21
+ export function getOrbExplorerUrl(addressOrSignature, type = 'address') {
22
+ return `https://orbmarkets.io/${type}/${addressOrSignature}`;
23
+ }
@@ -3,8 +3,8 @@ export declare function setApiKey(apiKey: string): void;
3
3
  export declare function getApiKey(): string;
4
4
  export declare function hasApiKey(): boolean;
5
5
  export declare function getHeliusClient(): HeliusClient;
6
- export declare function setNetwork(network: 'mainnet-beta' | 'devnet'): void;
7
- export declare function getNetwork(): 'mainnet-beta' | 'devnet';
6
+ export declare function setNetwork(network: 'mainnet' | 'devnet'): void;
7
+ export declare function getNetwork(): 'mainnet' | 'devnet';
8
8
  export declare function getRpcUrl(): string;
9
9
  export declare function getEnhancedWebSocketUrl(): string;
10
10
  export declare function getLaserstreamUrl(region?: 'ewr' | 'pitt' | 'slc' | 'lax' | 'lon' | 'ams' | 'fra' | 'tyo' | 'sgp'): string;
@@ -1,6 +1,6 @@
1
1
  import { createHelius } from 'helius-sdk';
2
2
  let sessionApiKey = null;
3
- let sessionNetwork = 'mainnet-beta';
3
+ let sessionNetwork = 'mainnet';
4
4
  let heliusClient = null;
5
5
  export function setApiKey(apiKey) {
6
6
  sessionApiKey = apiKey;
@@ -31,7 +31,7 @@ export function setNetwork(network) {
31
31
  }
32
32
  export function getNetwork() {
33
33
  const envNetwork = process.env.HELIUS_NETWORK;
34
- if (envNetwork === 'devnet' || envNetwork === 'mainnet-beta') {
34
+ if (envNetwork === 'devnet' || envNetwork === 'mainnet') {
35
35
  return envNetwork;
36
36
  }
37
37
  return sessionNetwork;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helius-mcp",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Official Helius MCP Server - Complete Solana blockchain data access for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,13 +12,7 @@
12
12
  "dev": "tsc --watch",
13
13
  "start": "node dist/index.js",
14
14
  "prepublishOnly": "pnpm build",
15
- "test": "vitest run",
16
- "test:watch": "vitest",
17
- "test:unit": "vitest run tests/unit",
18
- "test:integration": "vitest run tests/integration",
19
- "test:e2e": "vitest run tests/e2e",
20
- "test:live": "vitest run tests/live",
21
- "test:coverage": "vitest run --coverage"
15
+ "test": "vitest run"
22
16
  },
23
17
  "keywords": [
24
18
  "helius",