Skip to main content
Glama

Neo N3 MCP Server

by r3e-network
testing.htmlโ€ข31.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Testing Guide - Neo N3 MCP Server</title> <meta name="description" content="Comprehensive testing guide for Neo N3 MCP Server. Learn testing strategies, validation procedures, and quality assurance practices."> <meta name="keywords" content="neo, blockchain, mcp, testing, validation, quality assurance"> <!-- Favicon --> <link rel="icon" type="image/svg+xml" href="/assets/favicon.svg"> <!-- Fonts --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"> <!-- Modern Theme --> <link rel="stylesheet" href="/assets/css/modern-theme.css"> <style> .breadcrumb { color: var(--text-secondary); margin-bottom: var(--spacing-lg); } .breadcrumb a { color: var(--primary); text-decoration: none; } .example-section { margin-bottom: var(--spacing-3xl); } .example-section h2 { font-family: var(--font-heading); font-size: 1.75rem; font-weight: 600; margin-bottom: var(--spacing-lg); color: var(--text-primary); } .example-section h3 { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 600; margin: var(--spacing-xl) 0 var(--spacing-lg) 0; color: var(--text-primary); } .info-box { background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(6, 182, 212, 0.1)); border-left: 4px solid var(--primary); border-radius: var(--radius-md); padding: var(--spacing-lg); margin: var(--spacing-lg) 0; } .info-title { font-weight: 600; color: var(--primary); margin-bottom: var(--spacing-sm); } .code-block { margin: var(--spacing-lg) 0; } .code-header { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-md) var(--spacing-lg); background: var(--bg-tertiary); border-radius: var(--radius-md) var(--radius-md) 0 0; border-bottom: 1px solid var(--border-primary); } .code-title { color: var(--text-primary); font-weight: 500; } .copy-button { background: var(--bg-glass); border: 1px solid var(--border-primary); color: var(--text-secondary); padding: var(--spacing-xs) var(--spacing-sm); border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition); font-size: 0.8rem; } .copy-button:hover { background: var(--primary); color: white; } .code-block pre { background: var(--bg-tertiary); border-radius: 0 0 var(--radius-md) var(--radius-md); padding: var(--spacing-lg); margin: 0; overflow-x: auto; } .code-block code { color: var(--text-primary); font-family: var(--font-mono); font-size: 0.9rem; line-height: 1.6; } </style> </head> <body> <!-- Navigation --> <nav class="nav" id="nav"> <div class="nav-container"> <a href="/" class="nav-logo">Neo N3 MCP</a> <div class="nav-menu"> <a href="/" class="nav-link">Home</a> <a href="/#features" class="nav-link">Features</a> <a href="/docs" class="nav-link active">Docs</a> <a href="/examples" class="nav-link">Examples</a> <a href="https://github.com/r3e-network/neo-n3-mcp" class="btn btn-primary" target="_blank">Get Started</a> </div> </div> </nav> <div class="page-container"> <div class="breadcrumb"> <a href="/docs">Documentation</a> > Testing Guide </div> <header style="text-align: center; margin-bottom: 3rem;"> <h1 class="section-title">Testing Guide</h1> <p class="section-subtitle"> Comprehensive testing strategies and validation procedures for Neo N3 MCP Server </p> </header> <div class="example-section"> <h2>๐Ÿงช Testing Overview</h2> <p>Neo N3 MCP Server maintains 90%+ test coverage through a comprehensive testing strategy that includes unit tests, integration tests, security validation, and performance testing.</p> <div class="info-box"> <div class="info-title">๐Ÿ“Š Test Coverage Stats</div> <ul> <li><strong>395 Tests:</strong> Comprehensive test suite coverage</li> <li><strong>90%+ Coverage:</strong> High code coverage across all modules</li> <li><strong>34 Tools Tested:</strong> Every tool has dedicated test cases</li> <li><strong>9 Resources Tested:</strong> All resources validated</li> <li><strong>Security Tests:</strong> Extensive security validation</li> </ul> </div> </div> <div class="example-section"> <h2>๐Ÿ”ง Running Tests</h2> <h3>Development Testing</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">NPM Scripts</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-bash"># Run all tests npm test # Run tests with coverage npm run test:coverage # Run tests in watch mode npm run test:watch # Run specific test suite npm run test:unit npm run test:integration npm run test:security # Run tests with detailed output npm run test:verbose # Run performance tests npm run test:performance</code></pre> </div> <h3>Docker Testing</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Docker Test Environment</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-bash"># Build test image docker build -t neo-n3-mcp:test --target test . # Run tests in container docker run --rm neo-n3-mcp:test npm test # Run with test network docker-compose -f docker-compose.test.yml up --abort-on-container-exit # Interactive test environment docker run -it --rm neo-n3-mcp:test bash</code></pre> </div> </div> <div class="example-section"> <h2>๐ŸŽฏ Unit Testing</h2> <h3>Tool Testing Framework</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Example: Wallet Tool Tests</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">import { describe, it, expect, beforeEach, afterEach } from '@jest/globals' import { WalletService } from '../src/services/wallet-service' import { MockNeoRpcClient } from './mocks/neo-rpc-client' describe('WalletService', () => { let walletService: WalletService let mockRpcClient: MockNeoRpcClient beforeEach(() => { mockRpcClient = new MockNeoRpcClient() walletService = new WalletService(mockRpcClient) }) afterEach(() => { jest.clearAllMocks() }) describe('createWallet', () => { it('should create a new wallet with valid password', async () => { const result = await walletService.createWallet('secure-password-123') expect(result).toHaveProperty('address') expect(result).toHaveProperty('publicKey') expect(result.address).toMatch(/^N[A-Za-z0-9]{33}$/) expect(result.encrypted).toBe(true) }) it('should reject weak passwords', async () => { await expect(walletService.createWallet('123')) .rejects.toThrow('Password too weak') }) it('should handle network errors gracefully', async () => { mockRpcClient.setNetworkError(true) await expect(walletService.createWallet('secure-password-123')) .rejects.toThrow('Network connection failed') }) }) describe('getBalance', () => { it('should return balance for valid address', async () => { const address = 'NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj' mockRpcClient.setBalance(address, { NEO: '100', GAS: '50.5' }) const balance = await walletService.getBalance(address) expect(balance.NEO).toBe('100') expect(balance.GAS).toBe('50.5') }) it('should validate address format', async () => { await expect(walletService.getBalance('invalid-address')) .rejects.toThrow('Invalid address format') }) }) })</code></pre> </div> <h3>Contract Testing</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Famous Contracts Tests</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('ContractService', () => { describe('Famous Contracts', () => { it('should list all supported contracts', async () => { const contracts = await contractService.listFamousContracts() expect(contracts).toHaveLength(6) expect(contracts.map(c => c.name)).toEqual([ 'NeoFS', 'NeoBurger', 'Flamingo', 'NeoCompound', 'GrandShare', 'GhostMarket' ]) }) it('should get contract information', async () => { const contract = await contractService.getFamousContract('NeoFS') expect(contract).toHaveProperty('hash') expect(contract).toHaveProperty('name', 'NeoFS') expect(contract).toHaveProperty('description') expect(contract.methods).toBeInstanceOf(Array) }) it('should invoke read-only contract methods', async () => { const result = await contractService.invokeRead( 'NeoFS', 'totalSupply', [] ) expect(result).toHaveProperty('type', 'Integer') expect(result).toHaveProperty('value') }) }) })</code></pre> </div> </div> <div class="example-section"> <h2>๐Ÿ”— Integration Testing</h2> <h3>End-to-End MCP Protocol Testing</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">MCP Protocol Integration</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('MCP Protocol Integration', () => { let mcpServer: MCPServer beforeAll(async () => { mcpServer = new MCPServer() await mcpServer.initialize() }) afterAll(async () => { await mcpServer.shutdown() }) describe('Tools', () => { it('should list all available tools', async () => { const tools = await mcpServer.listTools() expect(tools).toHaveLength(34) expect(tools.every(tool => tool.name && tool.description)).toBe(true) }) it('should execute blockchain tools', async () => { const result = await mcpServer.callTool('get_blockchain_info', {}) expect(result.isError).toBe(false) expect(result.content).toHaveProperty('network') expect(result.content).toHaveProperty('blockHeight') }) it('should handle tool execution errors', async () => { const result = await mcpServer.callTool('get_balance', { address: 'invalid-address' }) expect(result.isError).toBe(true) expect(result.content).toContain('Invalid address format') }) }) describe('Resources', () => { it('should list all available resources', async () => { const resources = await mcpServer.listResources() expect(resources).toHaveLength(9) expect(resources.every(resource => resource.uri && resource.name)).toBe(true) }) it('should read network status resource', async () => { const content = await mcpServer.readResource('neo://network/status') expect(content).toHaveProperty('mimeType', 'application/json') expect(content.text).toBeTruthy() const data = JSON.parse(content.text) expect(data).toHaveProperty('network') expect(data).toHaveProperty('status') }) }) })</code></pre> </div> <h3>Network Integration Tests</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Neo N3 Network Integration</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('Neo N3 Network Integration', () => { describe('Testnet Integration', () => { it('should connect to testnet', async () => { const neoService = new NeoService('testnet') await neoService.initialize() const info = await neoService.getBlockchainInfo() expect(info.network).toBe('testnet') expect(info.blockHeight).toBeGreaterThan(0) }) it('should retrieve real block data', async () => { const block = await neoService.getBlock(1) expect(block).toHaveProperty('hash') expect(block).toHaveProperty('index', 1) expect(block).toHaveProperty('previousblockhash') expect(block.tx).toBeInstanceOf(Array) }) it('should handle network timeouts', async () => { const neoService = new NeoService('testnet', { timeout: 1 // Very short timeout }) await expect(neoService.getBlockchainInfo()) .rejects.toThrow(/timeout/i) }) }) describe('Famous Contracts Integration', () => { it('should interact with real NeoFS contract', async () => { const result = await contractService.invokeRead( 'NeoFS', 'symbol', [] ) expect(result.value).toBe('FS') }) it('should retrieve Flamingo token information', async () => { const result = await contractService.invokeRead( 'Flamingo', 'totalSupply', [] ) expect(parseInt(result.value)).toBeGreaterThan(0) }) }) })</code></pre> </div> </div> <div class="example-section"> <h2>๐Ÿ›ก๏ธ Security Testing</h2> <h3>Input Validation Tests</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Security Validation</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('Security Validation', () => { describe('Input Sanitization', () => { const maliciousInputs = [ '<script>alert("xss")</script>', 'javascript:alert("xss")', '../../etc/passwd', 'DROP TABLE users;', '${process.env.SECRET}', '\x00\x01\x02', 'A'.repeat(10000) // Large input ] maliciousInputs.forEach(input => { it(`should sanitize malicious input: ${input.substring(0, 20)}...`, async () => { await expect(mcpServer.callTool('get_balance', { address: input })).rejects.toThrow(/Invalid address format|Input validation failed/) }) }) }) describe('Rate Limiting', () => { it('should enforce rate limits', async () => { const promises = Array(150).fill(0).map(() => mcpServer.callTool('get_blockchain_info', {}) ) const results = await Promise.allSettled(promises) const rejected = results.filter(r => r.status === 'rejected') expect(rejected.length).toBeGreaterThan(0) expect(rejected.some(r => r.reason.message.includes('Rate limit exceeded') )).toBe(true) }) }) describe('Confirmation Requirements', () => { it('should require confirmation for write operations', async () => { await expect(mcpServer.callTool('transfer_assets', { fromWIF: 'test-key', toAddress: 'test-address', asset: 'GAS', amount: '1', confirm: false // Missing confirmation })).rejects.toThrow('Confirmation required') }) }) describe('Private Key Security', () => { it('should never log private keys', async () => { const consoleSpy = jest.spyOn(console, 'log') const errorSpy = jest.spyOn(console, 'error') try { await mcpServer.callTool('import_wallet', { key: 'KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr', password: 'test' }) } catch (e) { // Expected to fail in test environment } const allLogs = [ ...consoleSpy.mock.calls.flat(), ...errorSpy.mock.calls.flat() ].join(' ') expect(allLogs).not.toContain('KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr') consoleSpy.mockRestore() errorSpy.mockRestore() }) }) })</code></pre> </div> <h3>Network Security Tests</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Network Isolation</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('Network Security', () => { it('should isolate mainnet and testnet operations', async () => { const mainnetService = new NeoService('mainnet') const testnetService = new NeoService('testnet') const mainnetInfo = await mainnetService.getBlockchainInfo() const testnetInfo = await testnetService.getBlockchainInfo() expect(mainnetInfo.network).toBe('mainnet') expect(testnetInfo.network).toBe('testnet') expect(mainnetInfo.magic).not.toBe(testnetInfo.magic) }) it('should validate RPC endpoint certificates', async () => { const neoService = new NeoService('mainnet', { rpcUrl: 'https://invalid-certificate.example.com' }) await expect(neoService.getBlockchainInfo()) .rejects.toThrow(/certificate|SSL|TLS/) }) })</code></pre> </div> </div> <div class="example-section"> <h2>โšก Performance Testing</h2> <h3>Load Testing</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Performance Benchmarks</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('Performance Tests', () => { describe('Throughput', () => { it('should handle 100 concurrent requests', async () => { const startTime = Date.now() const promises = Array(100).fill(0).map((_, i) => mcpServer.callTool('get_blockchain_info', {}) ) const results = await Promise.all(promises) const endTime = Date.now() const duration = endTime - startTime const requestsPerSecond = 100 / (duration / 1000) expect(results.every(r => !r.isError)).toBe(true) expect(requestsPerSecond).toBeGreaterThan(10) // At least 10 RPS expect(duration).toBeLessThan(30000) // Under 30 seconds }) }) describe('Response Times', () => { const tools = [ 'get_blockchain_info', 'get_network_mode', 'list_famous_contracts' ] tools.forEach(toolName => { it(`should respond to ${toolName} within 2 seconds`, async () => { const startTime = Date.now() const result = await mcpServer.callTool(toolName, {}) const duration = Date.now() - startTime expect(result.isError).toBe(false) expect(duration).toBeLessThan(2000) // Under 2 seconds }) }) }) describe('Memory Usage', () => { it('should not leak memory under load', async () => { const initialMemory = process.memoryUsage().heapUsed // Perform many operations for (let i = 0; i < 1000; i++) { await mcpServer.callTool('get_blockchain_info', {}) if (i % 100 === 0) { global.gc && global.gc() // Force garbage collection if available } } const finalMemory = process.memoryUsage().heapUsed const memoryIncrease = finalMemory - initialMemory // Memory should not increase by more than 50MB expect(memoryIncrease).toBeLessThan(50 * 1024 * 1024) }) }) })</code></pre> </div> <h3>Cache Performance</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Cache Efficiency Tests</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-typescript">describe('Cache Performance', () => { it('should improve response times with caching', async () => { // Clear cache await cacheService.clear() // First request (cache miss) const start1 = Date.now() await mcpServer.callTool('get_blockchain_info', {}) const time1 = Date.now() - start1 // Second request (cache hit) const start2 = Date.now() await mcpServer.callTool('get_blockchain_info', {}) const time2 = Date.now() - start2 // Cache hit should be significantly faster expect(time2).toBeLessThan(time1 * 0.5) }) it('should maintain high cache hit rate', async () => { const operations = Array(100).fill(0).map(() => mcpServer.callTool('get_blockchain_info', {}) ) await Promise.all(operations) const cacheStats = await cacheService.getStats() expect(cacheStats.hitRate).toBeGreaterThan(0.8) // 80% hit rate }) })</code></pre> </div> </div> <div class="example-section"> <h2>๐Ÿค– Automated Testing</h2> <h3>CI/CD Testing Pipeline</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">GitHub Actions Test Workflow</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-yaml">name: Test Suite on: push: branches: [main, develop] pull_request: branches: [main] jobs: unit-tests: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20] steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm ci - run: npm run test:unit - run: npm run test:coverage - uses: codecov/codecov-action@v3 with: file: ./coverage/lcov.info integration-tests: runs-on: ubuntu-latest services: redis: image: redis ports: - 6379:6379 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 cache: 'npm' - run: npm ci - run: npm run test:integration env: NEO_NETWORK: testnet REDIS_URL: redis://localhost:6379 security-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 cache: 'npm' - run: npm ci - run: npm run test:security - run: npm audit --audit-level moderate performance-tests: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 cache: 'npm' - run: npm ci - run: npm run test:performance - name: Performance regression check run: | node scripts/check-performance-regression.js</code></pre> </div> <h3>Quality Gates</h3> <div class="info-box"> <div class="info-title">โœ… Quality Requirements</div> <ul> <li><strong>Test Coverage:</strong> Minimum 90% line coverage</li> <li><strong>Security Tests:</strong> All security tests must pass</li> <li><strong>Performance:</strong> No regression in key metrics</li> <li><strong>Integration:</strong> All Neo N3 integrations working</li> <li><strong>Code Quality:</strong> ESLint and TypeScript checks</li> </ul> </div> </div> <div class="example-section"> <h2>๐Ÿ“‹ Testing Checklist</h2> <h3>Pre-Release Testing</h3> <div class="warning-box"> <div class="warning-title">๐Ÿ” Manual Testing Checklist</div> <ul> <li>โœ… All 34 tools execute successfully</li> <li>โœ… All 9 resources return valid data</li> <li>โœ… Famous contracts integration working</li> <li>โœ… Wallet operations secure and functional</li> <li>โœ… Network switching (mainnet/testnet) works</li> <li>โœ… Error handling and validation proper</li> <li>โœ… Performance within acceptable ranges</li> <li>โœ… Security measures functioning</li> <li>โœ… Documentation examples verified</li> <li>โœ… Docker deployment tested</li> </ul> </div> <h3>Test Data Management</h3> <div class="code-block"> <div class="code-header"> <span class="code-title">Test Environment Setup</span> <button class="copy-button" onclick="copyCode(this)">Copy</button> </div> <pre><code class="language-bash"># Setup test environment npm run test:setup # Generate test wallets npm run test:generate-wallets # Setup test contracts npm run test:deploy-contracts # Cleanup test data npm run test:cleanup # Reset test environment npm run test:reset</code></pre> </div> </div> <div class="next-steps"> <h2>Next Steps</h2> <div class="step-cards"> <a href="/docs/architecture" class="step-card"> <h3>System Architecture</h3> <p>Understand the system design and testing implications</p> </a> <a href="/docs/deployment" class="step-card"> <h3>Production Deployment</h3> <p>Deploy with confidence using validated configurations</p> </a> <a href="/examples" class="step-card"> <h3>Examples</h3> <p>See tested examples and implementations in action</p> </a> </div> </div> </div> <!-- Footer --> <footer class="footer"> <div class="footer-container"> <div class="footer-grid"> <div> <div class="footer-brand">Neo N3 MCP</div> <p class="footer-description"> The most advanced Neo N3 blockchain development platform. Build powerful dApps with enterprise-grade tools and security. </p> </div> <div> <h4 class="footer-title">Product</h4> <div class="footer-links"> <a href="/docs" class="footer-link">Documentation</a> <a href="/examples" class="footer-link">Examples</a> <a href="/changelog" class="footer-link">Changelog</a> </div> </div> <div> <h4 class="footer-title">Resources</h4> <div class="footer-links"> <a href="https://docs.neo.org/" class="footer-link" target="_blank">Neo N3 Docs</a> <a href="https://modelcontextprotocol.io/" class="footer-link" target="_blank">MCP Protocol</a> <a href="https://www.npmjs.com/package/@r3e/neo-n3-mcp" class="footer-link" target="_blank">NPM Package</a> </div> </div> <div> <h4 class="footer-title">Community</h4> <div class="footer-links"> <a href="https://github.com/r3e-network/neo-n3-mcp" class="footer-link" target="_blank">GitHub</a> <a href="https://github.com/r3e-network/neo-n3-mcp/discussions" class="footer-link" target="_blank">Discussions</a> <a href="https://discord.gg/neo" class="footer-link" target="_blank">Discord</a> </div> </div> </div> <div class="footer-bottom"> <p>ยฉ 2025 Neo N3 MCP. Open source under MIT License.</p> <p>Built with โค๏ธ for the Neo ecosystem</p> </div> </div> </footer> <script> // Navigation scroll effect window.addEventListener('scroll', () => { const nav = document.getElementById('nav'); if (window.scrollY > 50) { nav.classList.add('scrolled'); } else { nav.classList.remove('scrolled'); } }); function copyCode(button) { const codeBlock = button.closest('.code-block').querySelector('code'); const text = codeBlock.textContent; navigator.clipboard.writeText(text).then(() => { button.textContent = 'Copied!'; setTimeout(() => { button.textContent = 'Copy'; }, 2000); }); } </script> </body> </html>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/r3e-network/neo-n3-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server