example-usage.js•6.84 kB
#!/usr/bin/env node
/**
* Example usage of Aptos MCP Server
* This demonstrates how to integrate the MCP server into your own applications
*/
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
class AptosMCPClient {
constructor(privateKey, network = 'testnet') {
this.privateKey = privateKey;
this.network = network;
this.server = null;
this.requestId = 1;
this.pendingRequests = new Map();
}
async start() {
console.log('🚀 Starting Aptos MCP Client...');
const env = {
...process.env,
APTOS_MCP_PRIVATE_KEY: this.privateKey,
APTOS_MCP_NETWORK: this.network
};
const serverPath = join(__dirname, 'build', 'index.js');
this.server = spawn('node', [serverPath], {
env,
stdio: ['pipe', 'pipe', 'pipe']
});
this.server.stdout.on('data', (data) => {
const lines = data.toString().split('\n').filter(line => line.trim());
for (const line of lines) {
try {
const response = JSON.parse(line);
if (response.id && this.pendingRequests.has(response.id)) {
const { resolve } = this.pendingRequests.get(response.id);
this.pendingRequests.delete(response.id);
resolve(response);
}
} catch (e) {
// Ignore non-JSON lines
}
}
});
this.server.stderr.on('data', (data) => {
const output = data.toString();
if (output.includes('Aptos Blockchain MCP Server running on stdio')) {
console.log('✅ MCP Server ready');
} else {
console.error('Server error:', output);
}
});
// Wait for server to start
await new Promise(resolve => setTimeout(resolve, 1000));
}
async callTool(toolName, args = {}) {
return new Promise((resolve, reject) => {
const id = this.requestId++;
const request = {
jsonrpc: '2.0',
id,
method: 'tools/call',
params: {
name: toolName,
arguments: args
}
};
this.pendingRequests.set(id, { resolve, reject });
this.server.stdin.write(JSON.stringify(request) + '\n');
// Timeout after 30 seconds
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error(`Timeout calling ${toolName}`));
}
}, 30000);
});
}
async listTools() {
return new Promise((resolve, reject) => {
const id = this.requestId++;
const request = {
jsonrpc: '2.0',
id,
method: 'tools/list'
};
this.pendingRequests.set(id, { resolve, reject });
this.server.stdin.write(JSON.stringify(request) + '\n');
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error('Timeout listing tools'));
}
}, 10000);
});
}
// Convenience methods for common operations
async createAccount() {
const response = await this.callTool('create_account');
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
async getBalance(address) {
const response = await this.callTool('get_apt_balance', { account_address: address });
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
async transferAPT(recipientAddress, amount) {
const response = await this.callTool('transfer_apt', {
recipient_address: recipientAddress,
amount: amount.toString()
});
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
async fundAccount(address, amount = 1) {
const response = await this.callTool('fund_account', {
account_address: address,
amount
});
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
async getAccountInfo(address) {
const response = await this.callTool('get_account_info', { account_address: address });
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
async getTransactionStatus(txHash) {
const response = await this.callTool('get_transaction_status', { transaction_hash: txHash });
if (response.result.isError) {
throw new Error(response.result.content[0].text);
}
return response.result.content[0].text;
}
stop() {
if (this.server) {
this.server.kill();
}
}
}
// Example usage
async function demonstrateUsage() {
// Replace with your actual private key for real testing
const privateKey = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
const client = new AptosMCPClient(privateKey, 'testnet');
try {
await client.start();
console.log('\n📋 Available Tools:');
const toolsResponse = await client.listTools();
toolsResponse.result.tools.forEach(tool => {
console.log(` • ${tool.name}`);
});
console.log('\n👤 Creating new account...');
const newAccountInfo = await client.createAccount();
console.log(newAccountInfo);
// Extract address from the response (this is a simple example)
const addressMatch = newAccountInfo.match(/Address: (0x[a-fA-F0-9]+)/);
if (addressMatch) {
const newAddress = addressMatch[1];
console.log('\n💰 Checking balance of new account...');
try {
const balance = await client.getBalance(newAddress);
console.log(balance);
} catch (error) {
console.log('Expected: New account has no balance yet');
}
console.log('\n🚰 Funding new account...');
try {
const fundResult = await client.fundAccount(newAddress, 1);
console.log(fundResult);
console.log('\n💰 Checking balance after funding...');
const newBalance = await client.getBalance(newAddress);
console.log(newBalance);
} catch (error) {
console.log('Note: Funding might fail if faucet is unavailable');
console.log('Error:', error.message);
}
}
console.log('\n✅ Demo completed successfully!');
} catch (error) {
console.error('❌ Demo failed:', error.message);
} finally {
client.stop();
}
}
// Run the demonstration
if (import.meta.url === `file://${process.argv[1]}`) {
demonstrateUsage().catch(console.error);
}
export { AptosMCPClient };