Repository navigation
Wire up Sparkle so the app actually checks for updates - #180
Merged
Merged
Conversation
Info.plist has declared SUFeedURL/SUPublicEDKey (and the entitlements reserve Sparkle's -spks/-spki XPC mach ports) since day one, but no target ever linked the Sparkle package or instantiated an updater. The result: every install is permanently frozen at whatever version it first shipped, silently, with no error and no "Check for Updates" menu item to surface the problem. This is why users can stay on known-crashy builds indefinitely: my own installed copy was v1.4.0 (Jan 2026), three months and one release behind the fix for the Bonjour-disconnect crash in mattt#166/1.4.1, with no way to find out short of reading raw Claude Desktop MCP logs. - Add the Sparkle SPM package to the iMCP app target. - Construct SPUStandardUpdaterController(startingUpdater: true, ...) in App.swift so Sparkle's normal periodic background check actually runs, using the existing SUFeedURL/SUPublicEDKey. - Add a "Check for Updates..." item to the menu bar dropdown, wired to updater.checkForUpdates() and disabled while a check is unavailable. Verified: package graph resolves, `xcodebuild build -scheme iMCP` succeeds, the built app launches and stays up with Sparkle.framework loaded, `imcp-serverTests` (incl. ServiceGroupConfigurationTests) still pass, and `swift format lint --strict --recursive .` is clean. Note: https://downloads.imcp.app/appcast.xml (the configured SUFeedURL) currently fails to resolve in DNS (NXDOMAIN), so this alone won't help until that feed is live — flagging separately in the PR description.
Owner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
iMCP never checks for updates. Every install is stuck on whatever version it first shipped — silently, with no error, no in-app way to check, and no prompt when a fix ships.
Info.plistdeclaresSUFeedURL,SUPublicEDKey, andSUEnableInstallerLauncherService— it looks like Sparkle is configured — but no target links the Sparkle package and no code constructs an updater, so those keys are dead. This PR links Sparkle and wires it up.Root cause
Found on a real install stuck on v1.4.0 (Jan 2026 build), still hitting the
ServiceGroupErrorfatal crash from #166 three months after the fix shipped in v1.4.1. There's noSPUStandardUpdaterControlleror equivalent anywhere in the codebase, so the Sparkle keys in Info.plist are config with nothing reading them.Fix
iMCPapp target.SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)inApp.swift, using the existingSUFeedURL/SUPublicEDKey.updater.checkForUpdates().Test plan
xcodebuild -resolvePackageDependenciesresolves Sparkle (2.9.6) alongside existing depsxcodebuild build -scheme iMCP -configuration DebugsucceedsSparkle.frameworkloadedxcodebuild test -scheme imcp-serverTests— all pass, includingServiceGroupConfigurationTests(unrelated, confirms no regression)swift format lint --strict --recursive .— cleanTTY35UM57SDeveloper ID or the WeatherKit entitlement, so CI's signed build is the real check for that.Scope / non-goals
downloads.imcp.app(the configuredSUFeedURL) doesn't resolve — NXDOMAIN. This makes the app actually attempt update checks, but they'll fail until that domain is live. Noappcast.xmlor publish workflow in this repo, so I can't tell if it's stale or just needs DNS pointed at wherever the appcast is hosted.Closes #52.