Skip to content

Commit b69f61b

Browse files
committed
fix(swift): use typed params for size-changed and always attempt teardown
1. Size-changed notification now properly decodes to McpUiSizeChangedParams using JSONDecoder, with fallback to manual NSNumber extraction. 2. Teardown now always attempts to send the teardown request even if the app hasn't fully initialized (matching web host behavior). Previously it would skip teardown if isReady() returned false, causing the card to disappear immediately without giving the app a chance to clean up.
1 parent 666c90d commit b69f61b

2 files changed

Lines changed: 25 additions & 18 deletions

File tree

examples/basic-host-swift/Sources/BasicHostApp/McpHostViewModel.swift

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -575,20 +575,15 @@ class ToolCallInfo: ObservableObject, Identifiable {
575575
var errorMessage: String?
576576

577577
if let bridge = appBridge {
578-
// Only send teardown if the bridge is initialized
579-
// If not initialized, the app hasn't done anything worth saving
580-
let isReady = await bridge.isReady()
581-
if isReady {
582-
logger.info("Sending teardown request...")
583-
do {
584-
_ = try await bridge.sendResourceTeardown()
585-
logger.info("Teardown request completed successfully")
586-
} catch {
587-
logger.error("Teardown request failed: \(String(describing: error))")
588-
errorMessage = "Teardown failed: app may not have saved data"
589-
}
590-
} else {
591-
logger.info("Skipping teardown - bridge not yet initialized")
578+
// Always attempt teardown - the app should handle it gracefully
579+
// even if not fully initialized (matching web host behavior)
580+
logger.info("Sending teardown request...")
581+
do {
582+
_ = try await bridge.sendResourceTeardown()
583+
logger.info("Teardown request completed successfully")
584+
} catch {
585+
// Teardown failed - app may have already closed or wasn't initialized
586+
logger.warning("Teardown request failed (app may have already closed): \(String(describing: error))")
592587
}
593588

594589
logger.info("Closing bridge...")

swift/Sources/McpApps/AppBridge.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,22 @@ public actor AppBridge {
107107
isInitialized = true
108108
onInitialized?()
109109
case "ui/notifications/size-changed":
110-
// Handle both Int and Double from JSON (integers decode as Int, not Double)
111-
let width = (notification.params?["width"]?.value as? NSNumber)?.intValue
112-
let height = (notification.params?["height"]?.value as? NSNumber)?.intValue
113-
onSizeChange?(width, height)
110+
// Decode to typed params - handles both Int and Double from JSON
111+
if let paramsDict = notification.params {
112+
do {
113+
let data = try JSONSerialization.data(withJSONObject: paramsDict.mapValues { $0.value })
114+
let params = try JSONDecoder().decode(McpUiSizeChangedNotificationParams.self, from: data)
115+
// Convert Double? to Int? for callback
116+
let width = params.width.map { Int($0) }
117+
let height = params.height.map { Int($0) }
118+
onSizeChange?(width, height)
119+
} catch {
120+
// Fallback: manually extract values (handles Int/Double mismatch)
121+
let width = (paramsDict["width"]?.value as? NSNumber)?.intValue
122+
let height = (paramsDict["height"]?.value as? NSNumber)?.intValue
123+
onSizeChange?(width, height)
124+
}
125+
}
114126
case "notifications/message":
115127
if let level = notification.params?["level"]?.value as? String,
116128
let logLevel = LogLevel(rawValue: level),

0 commit comments

Comments
 (0)