Skip to main content
Glama

ldk_channel_status

Track and manage Lightning Network channel states and balances in real-time using this tool, enabling developers to include offline channels and optimize wallet performance for iOS Lightning applications.

Instructions

Monitor channel states and balances while coding

Input Schema

NameRequiredDescriptionDefault
includeOfflineNoInclude offline/unusable channels

Input Schema (JSON Schema)

{ "properties": { "includeOffline": { "default": true, "description": "Include offline/unusable channels", "type": "boolean" } }, "type": "object" }

Implementation Reference

  • The main handler function for the ldk_channel_status tool. Fetches channel status from LightningService, filters offline channels if requested, computes aggregate balances, returns formatted JSON summary and detailed channels list with iOS SwiftUI example code.
    execute: async (args: any): Promise<ToolResult> => { try { const channels = await lightningService.getChannelStatus(); const filteredChannels = args.includeOffline === false ? channels.filter(c => c.isUsable) : channels; const totalCapacity = channels.reduce((sum, c) => sum + c.capacityMsat, 0); const totalLocal = channels.reduce((sum, c) => sum + c.localBalanceMsat, 0); const totalRemote = channels.reduce((sum, c) => sum + c.remoteBalanceMsat, 0); return { content: [{ type: 'text', text: JSON.stringify({ success: true, summary: { totalChannels: channels.length, usableChannels: channels.filter(c => c.isUsable).length, totalCapacitySats: Math.floor(totalCapacity / 1000), totalLocalSats: Math.floor(totalLocal / 1000), totalRemoteSats: Math.floor(totalRemote / 1000) }, channels: filteredChannels.map(c => ({ channelId: c.channelId, shortChannelId: c.shortChannelId, remotePubkey: c.remotePubkey, state: c.state, isUsable: c.isUsable, capacitySats: Math.floor(c.capacityMsat / 1000), localBalanceSats: Math.floor(c.localBalanceMsat / 1000), remoteBalanceSats: Math.floor(c.remoteBalanceMsat / 1000) })), swiftExample: ` // Swift code to display channel status in your iOS app import SwiftUI import LightningDevKit struct ChannelListView: View { @State private var channels: [ChannelDetails] = [] @State private var isLoading = true var body: some View { NavigationView { List { // Summary Section Section("Summary") { HStack { Label("Total Capacity", systemImage: "bolt.circle") Spacer() Text("\\(totalCapacitySats) sats") .foregroundColor(.secondary) } HStack { Label("Local Balance", systemImage: "arrow.up.circle") .foregroundColor(.green) Spacer() Text("\\(totalLocalSats) sats") .foregroundColor(.secondary) } HStack { Label("Remote Balance", systemImage: "arrow.down.circle") .foregroundColor(.blue) Spacer() Text("\\(totalRemoteSats) sats") .foregroundColor(.secondary) } } // Channels Section Section("Channels (\\(usableChannels)/\\(channels.count))") { ForEach(channels, id: \\.channelId) { channel in ChannelRow(channel: channel) } } } .navigationTitle("Lightning Channels") .refreshable { await loadChannels() } .overlay { if isLoading { ProgressView() } } } .task { await loadChannels() } } var totalCapacitySats: Int { channels.reduce(0) { $0 + Int($1.channelValueSatoshis) } } var totalLocalSats: Int { channels.reduce(0) { $0 + Int($1.balanceMsat / 1000) } } var totalRemoteSats: Int { channels.reduce(0) { total, channel in total + Int(channel.channelValueSatoshis) - Int(channel.balanceMsat / 1000) } } var usableChannels: Int { channels.filter { $0.isUsable }.count } func loadChannels() async { isLoading = true defer { isLoading = false } // Get channels from LDK let channelManager = LDKManager.shared.channelManager channels = channelManager.listChannels() } } struct ChannelRow: View { let channel: ChannelDetails var body: some View { VStack(alignment: .leading, spacing: 8) { // Channel state indicator HStack { Circle() .fill(channel.isUsable ? Color.green : Color.orange) .frame(width: 10, height: 10) Text(channelStateText) .font(.caption) .foregroundColor(.secondary) Spacer() if let scid = channel.getShortChannelId() { Text(scid.description) .font(.caption2) .foregroundColor(.secondary) } } // Balance bar GeometryReader { geometry in ZStack(alignment: .leading) { // Background RoundedRectangle(cornerRadius: 4) .fill(Color.gray.opacity(0.2)) .frame(height: 20) // Local balance RoundedRectangle(cornerRadius: 4) .fill(Color.green) .frame( width: geometry.size.width * localBalanceRatio, height: 20 ) } } .frame(height: 20) // Balance text HStack { Text("\\(localBalanceSats) sats") .font(.caption) .foregroundColor(.green) Spacer() Text("\\(remoteBalanceSats) sats") .font(.caption) .foregroundColor(.blue) } } .padding(.vertical, 4) } var channelStateText: String { if channel.isUsable { return "Active" } else if channel.isChannelReady { return "Ready" } else { return "Pending" } } var localBalanceSats: Int { Int(channel.balanceMsat / 1000) } var remoteBalanceSats: Int { Int(channel.channelValueSatoshis) - localBalanceSats } var localBalanceRatio: Double { Double(channel.balanceMsat) / Double(channel.channelValueSatoshis * 1000) } }`.trim() }, 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 optional 'includeOffline' boolean parameter for the tool.
    inputSchema: { type: 'object', properties: { includeOffline: { type: 'boolean', description: 'Include offline/unusable channels', default: true } } },
  • src/index.ts:38-62 (registration)
    Registration of all tools in the MCP server, including getChannelStatusTool in the tools array used for listTools and callTool handling.
    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, ];
  • Helper method in LightningService that provides the raw channel data used by the tool handler.
    async getChannelStatus(): Promise<Channel[]> { return Array.from(this.channels.values()); }

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