Skip to main content
Glama
StevenGeller

LDK MCP Server

by StevenGeller

ldk_get_architecture

Retrieve iOS Lightning wallet architecture patterns and best practices for project structure, security, data flow, testing, deployment, or performance.

Instructions

Get iOS Lightning wallet architecture patterns and best practices

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
topicYesArchitecture topic to explore

Implementation Reference

  • The main handler function that returns hardcoded iOS Lightning wallet architecture guides based on the requested topic (project_structure, security_architecture, etc.).
      execute: async (args: any): Promise<ToolResult> => {
        const architectureGuides: Record<string, any> = {
          project_structure: {
            title: 'iOS Lightning Wallet Project Structure',
            overview: 'Modular architecture with clear separation of concerns',
            structure: `
    LightningWallet/
    ├── App/
    │   ├── LightningWalletApp.swift
    │   ├── AppDelegate.swift
    │   └── Info.plist
    ├── Core/
    │   ├── LDK/
    │   │   ├── LDKManager.swift
    │   │   ├── ChannelManager+Extensions.swift
    │   │   ├── EventHandler.swift
    │   │   └── Persistence/
    │   ├── Bitcoin/
    │   │   ├── WalletManager.swift
    │   │   ├── AddressManager.swift
    │   │   └── TransactionBuilder.swift
    │   └── Networking/
    │       ├── PeerConnection.swift
    │       ├── ElectrumClient.swift
    │       └── RapidGossipSync.swift
    ├── Features/
    │   ├── Wallet/
    │   │   ├── Views/
    │   │   ├── ViewModels/
    │   │   └── Models/
    │   ├── Channels/
    │   │   ├── Views/
    │   │   ├── ViewModels/
    │   │   └── Services/
    │   ├── Payments/
    │   │   ├── Send/
    │   │   ├── Receive/
    │   │   └── History/
    │   └── Settings/
    │       ├── Security/
    │       ├── Network/
    │       └── Backup/
    ├── Shared/
    │   ├── UI/
    │   │   ├── Components/
    │   │   ├── Styles/
    │   │   └── Extensions/
    │   ├── Utils/
    │   │   ├── Crypto/
    │   │   ├── Formatting/
    │   │   └── Validation/
    │   └── Services/
    │       ├── KeychainService.swift
    │       ├── BiometricService.swift
    │       └── NotificationService.swift
    └── Resources/
        ├── Assets.xcassets
        ├── Localizable.strings
        └── LaunchScreen.storyboard`,
            designPatterns: [
              'MVVM for UI architecture',
              'Repository pattern for data access',
              'Coordinator pattern for navigation',
              'Factory pattern for LDK object creation',
              'Observer pattern for Lightning events'
            ],
            dependencies: {
              'LightningDevKit': 'Lightning protocol implementation',
              'BitcoinDevKit': 'On-chain wallet functionality',
              'SwiftUI': 'Modern declarative UI',
              'Combine': 'Reactive programming',
              'CryptoKit': 'Cryptographic operations'
            }
          },
    
          security_architecture: {
            title: 'Security Architecture for iOS Lightning Wallet',
            layers: {
              'Key Management': {
                description: 'Secure generation, storage, and usage of cryptographic keys',
                implementation: `
    // Secure Key Management
    class SecureKeyManager {
        private let keychain: KeychainService
        private let secureEnclave: SecureEnclaveService
        
        // Key generation with Secure Enclave
        func generateNodeKey() throws -> SecKey {
            let access = SecAccessControlCreateWithFlags(
                nil,
                kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
                [.privateKeyUsage, .biometryCurrentSet],
                nil
            )!
            
            let attributes: [String: Any] = [
                kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
                kSecAttrKeySizeInBits as String: 256,
                kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
                kSecPrivateKeyAttrs as String: [
                    kSecAttrIsPermanent as String: true,
                    kSecAttrApplicationTag as String: "com.app.lightning.nodekey",
                    kSecAttrAccessControl as String: access
                ]
            ]
            
            var error: Unmanaged<CFError>?
            guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
                throw error!.takeRetainedValue() as Error
            }
            
            return privateKey
        }
        
        // Encrypted seed storage
        func storeSeed(_ seed: Data) throws {
            let encryptedSeed = try encryptWithHardwareKey(seed)
            try keychain.store(
                encryptedSeed,
                for: "lightning_seed",
                withBiometricProtection: true
            )
        }
    }`,
                bestPractices: [
                  'Use Secure Enclave for key generation when possible',
                  'Enable biometric protection for all sensitive operations',
                  'Implement key rotation strategies',
                  'Use hardware-backed encryption',
                  'Clear sensitive data from memory immediately after use'
                ]
              },
              'Network Security': {
                description: 'Secure communication with Lightning peers and Bitcoin nodes',
                implementation: `
    // Tor Integration for Privacy
    class TorManager {
        private var torThread: TorThread?
        private var torConfiguration: TorConfiguration
        
        func startTor() async throws {
            torConfiguration = TorConfiguration()
            torConfiguration.cookieAuthentication = true
            torConfiguration.dataDirectory = getTorDataDirectory()
            
            torThread = TorThread(configuration: torConfiguration)
            try await torThread?.start()
            
            // Wait for Tor to be ready
            await waitForTorConnection()
        }
        
        func createTorSocket(to address: String, port: UInt16) -> TorSocket {
            return TorSocket(
                socksHost: "127.0.0.1",
                socksPort: torConfiguration.socksPort,
                destinationHost: address,
                destinationPort: port
            )
        }
    }`,
                protocols: [
                  'Use Tor for all Lightning peer connections',
                  'Certificate pinning for API endpoints',
                  'Noise protocol for peer communication',
                  'No plaintext storage of sensitive data',
                  'Regular security audits'
                ]
              },
              'Application Security': {
                description: 'App-level security measures',
                features: [
                  'Jailbreak detection',
                  'Anti-debugging protection',
                  'Code obfuscation for critical paths',
                  'Runtime application self-protection (RASP)',
                  'Secure backup and restore'
                ]
              }
            }
          },
    
          data_flow: {
            title: 'Lightning Wallet Data Flow Architecture',
            flows: {
              'Payment Flow': {
                description: 'End-to-end payment processing',
                steps: [
                  '1. User initiates payment in UI',
                  '2. ViewModel validates input and creates payment request',
                  '3. LDKManager finds route via Router',
                  '4. ChannelManager sends payment through Lightning network',
                  '5. EventHandler processes payment events',
                  '6. Persistence layer saves payment record',
                  '7. UI updates with payment status'
                ],
                diagram: `
    UI Layer          Business Layer       LDK Layer         Network Layer
       │                    │                  │                  │
       ├─ Send Payment ────>│                  │                  │
       │                    ├─ Validate ──────>│                  │
       │                    │                  ├─ Find Route ────>│
       │                    │                  │<─── Route ───────┤
       │                    │                  ├─ Send HTLC ─────>│
       │                    │<─ Payment Event ─┤                  │
       │<─ Update Status ───┤                  │                  │
       │                    ├─ Save Record ───>│                  │
       │                    │                  │                  │`
              },
              'Channel Management': {
                description: 'Channel lifecycle management',
                states: [
                  'Pending -> Opening -> Open -> Active',
                  'Active -> Closing -> Closed',
                  'Any State -> Force Closing -> Closed'
                ]
              }
            }
          },
    
          testing_strategy: {
            title: 'Comprehensive Testing Strategy',
            levels: {
              'Unit Tests': {
                coverage: '80%+ for business logic',
                framework: 'XCTest',
                example: `
    class ChannelManagerTests: XCTestCase {
        var sut: ChannelManager!
        var mockLDK: MockLDKManager!
        
        override func setUp() {
            super.setUp()
            mockLDK = MockLDKManager()
            sut = ChannelManager(ldkManager: mockLDK)
        }
        
        func testOpenChannel_WithValidInputs_CreatesChannel() async throws {
            // Given
            let expectedCapacity: UInt64 = 100000
            let remotePubkey = TestData.validPubkey
            
            // When
            let channel = try await sut.openChannel(
                remotePubkey: remotePubkey,
                capacity: expectedCapacity
            )
            
            // Then
            XCTAssertEqual(channel.capacity, expectedCapacity)
            XCTAssertEqual(channel.remotePubkey, remotePubkey)
            XCTAssertTrue(mockLDK.createChannelCalled)
        }
    }`
              },
              'Integration Tests': {
                coverage: 'Critical user flows',
                tools: ['XCUITest', 'Appium'],
                scenarios: [
                  'Complete payment flow',
                  'Channel open/close cycle',
                  'Backup and restore',
                  'Network disruption handling'
                ]
              },
              'Lightning Network Tests': {
                description: 'Testing with real Lightning testnet',
                setup: 'Automated testnet node deployment',
                cases: [
                  'Multi-hop payments',
                  'Channel force close',
                  'Payment timeout handling',
                  'Fee estimation accuracy'
                ]
              }
            }
          },
    
          deployment: {
            title: 'Deployment Architecture',
            environments: {
              'Development': {
                network: 'Regtest',
                features: ['Debug logging', 'Mock services', 'Test shortcuts'],
                backend: 'Local Bitcoin Core + CLN'
              },
              'Staging': {
                network: 'Testnet',
                features: ['Real Lightning connections', 'TestFlight distribution'],
                backend: 'Hosted testnet infrastructure'
              },
              'Production': {
                network: 'Mainnet',
                features: ['Full security', 'Analytics', 'Crash reporting'],
                backend: 'Redundant node infrastructure'
              }
            },
            cicd: {
              pipeline: [
                'Code commit -> GitHub Actions',
                'Run tests (unit, integration, UI)',
                'Security scanning (SAST/DAST)',
                'Build and sign IPA',
                'Deploy to TestFlight/App Store'
              ],
              tools: {
                'Fastlane': 'Automation and deployment',
                'Bitrise': 'CI/CD platform',
                'Firebase': 'Crash reporting and analytics',
                'Sentry': 'Error tracking'
              }
            }
          },
    
          performance: {
            title: 'Performance Optimization Architecture',
            strategies: {
              'Memory Management': [
                'Lazy loading of channel data',
                'Pagination for payment history',
                'Efficient image caching for QR codes',
                'Proper cleanup of LDK objects'
              ],
              'Network Optimization': [
                'Connection pooling for peers',
                'Batched gossip updates',
                'Compressed data transmission',
                'Smart retry mechanisms'
              ],
              'UI Performance': [
                'SwiftUI view optimization',
                'Async image loading',
                'List virtualization',
                'Smooth animations at 60fps'
              ],
              'Battery Optimization': [
                'Intelligent background sync',
                'Reduced network polling',
                'Efficient cryptographic operations',
                'Wake lock management'
              ]
            },
            monitoring: `
    // Performance Monitoring
    class PerformanceMonitor {
        static let shared = PerformanceMonitor()
        
        func trackLightningOperation<T>(
            _ operation: String,
            block: () async throws -> T
        ) async rethrows -> T {
            let startTime = CFAbsoluteTimeGetCurrent()
            let startMemory = getMemoryUsage()
            
            defer {
                let duration = CFAbsoluteTimeGetCurrent() - startTime
                let memoryDelta = getMemoryUsage() - startMemory
                
                Analytics.track("lightning_operation", [
                    "operation": operation,
                    "duration_ms": duration * 1000,
                    "memory_delta_mb": memoryDelta / 1024 / 1024
                ])
            }
            
            return try await block()
        }
    }`
          }
        };
    
        try {
          const guide = architectureGuides[args.topic];
          if (!guide) {
            throw new Error(`Unknown topic: ${args.topic}`);
          }
    
          return {
            content: [{
              type: 'text',
              text: JSON.stringify({
                success: true,
                topic: args.topic,
                content: guide
              }, null, 2)
            }]
          };
        } catch (error) {
          return {
            content: [{
              type: 'text',
              text: JSON.stringify({
                success: false,
                error: error instanceof Error ? error.message : 'Unknown error'
              }, null, 2)
            }],
            isError: true
          };
        }
      }
  • Input schema defining the 'topic' parameter with allowed enum values for architecture guides.
    inputSchema: {
      type: 'object',
      properties: {
        topic: {
          type: 'string',
          enum: [
            'project_structure',
            'security_architecture',
            'data_flow',
            'testing_strategy',
            'deployment',
            'performance'
          ],
          description: 'Architecture topic to explore'
        }
      },
      required: ['topic']
    },
  • src/index.ts:38-62 (registration)
    Registration of all tools in the MCP server, including getArchitectureTool at line 57.
    const tools = [
      generateInvoiceTool,
      payInvoiceTool,
      getChannelStatusTool,
      getNodeInfoTool,
      backupStateTool,
      keychainTestTool,
      backgroundTestTool,
      pushNotificationTool,
      biometricAuthTool,
      createChannelTool,
      closeChannelTool,
      getBalanceTool,
      decodeInvoiceTool,
      listPaymentsTool,
      estimateFeeTool,
      generateMnemonicTool,
      deriveAddressTool,
      getSwiftCodeTool,
      getArchitectureTool,
      testScenarioTool,
      networkGraphTool,
      eventHandlingTool,
      chainSyncTool,
    ];
  • src/index.ts:31-31 (registration)
    Import statement for the getArchitectureTool.
    import { getArchitectureTool } from './tools/getArchitecture.js';
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states this is a 'Get' operation, implying read-only behavior, but doesn't clarify if it requires authentication, has rate limits, returns structured data or documentation, or involves any side effects. For a tool with no annotations, this leaves significant gaps in understanding its behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose without unnecessary words. It is front-loaded with the key action and resource, making it easy to parse quickly. Every part of the sentence contributes essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has one well-documented parameter (100% schema coverage) and no output schema, the description is minimally adequate but lacks depth. It doesn't explain what the output looks like (e.g., text, structured data), potential errors, or how it integrates with other tools. For a tool with no annotations and no output schema, more context on behavior and results would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, with the 'topic' parameter fully documented via its enum values (e.g., 'project_structure', 'security_architecture'). The description adds no additional parameter semantics beyond what the schema provides, such as explaining what each topic entails or how topics relate. With high schema coverage, the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Get') and the resource ('iOS Lightning wallet architecture patterns and best practices'), making the purpose specific and understandable. However, it doesn't explicitly differentiate from sibling tools like 'ldk_get_swift_code' or 'ldk_get_balance', which also retrieve information but about different aspects of the Lightning wallet.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, context for selecting specific topics, or how it relates to sibling tools like 'ios_background_test' or 'ldk_test_scenario' that might involve architecture testing. Usage is implied only by the tool name and description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/StevenGeller/ldk-mcp'

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