You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remove the MCP Optimizer feature from the ToolHive Studio UI and ensure that users upgrading from a version where the optimizer was enabled are migrated cleanly on startup, so they don't end up with an orphaned __mcp-optimizer__ group, a dangling meta-mcp workload, or clients registered to a group that no longer has a UI surface.
This follows #1910, which shipped the deprecation banner and prepared users for the sunset.
Why
The MCP Optimizer was an experimental feature that has been deprecated. Keeping the code, routes, hooks, and UI branches around adds maintenance cost, complicates the MCP servers / groups / clients flows with optimizer-specific branches, and leaves users who had previously enabled it in an inconsistent state after upgrade.
Scope
Remove from the product
Route + UI surface: /mcp-optimizer, the sunset banner (McpOptimizerSunsetBanner), the entire features/meta-mcp module (group selector, loading dialog, optimizer warnings, and backing hooks).
All optimizer-specific branches in the MCP servers sidebar, group actions, network isolation tab, local-mcp form, clients button, and the registry / run-custom / run-remote / update / restart / stop / delete orchestration.
Supporting hooks: use-create-optimizer-group, use-optimize-group-name, use-is-optimized-group-name, use-mcp-optimizer-banner-visible, use-notification-optimizer, and their tests.
Config: drop the toolhive-mcp-optimizer image from renovate.json, drop MCP_OPTIMIZER_SUNSET_BLOG_URL from common/app-info.ts, trim constants.ts down to the identifiers still needed by the cleanup migration.
Keep for one release
META_OPTIMIZER remains in the feature-flag registry but set to isDisabled: true. It never shows up in experimental settings and always returns false, but the key is preserved so the cleanup path can observe prior state. To be removed entirely in the next release.
MCP_OPTIMIZER_GROUP_NAME / META_MCP_SERVER_NAME constants stay in constants.ts because the cleanup hook depends on them. They can be inlined or deleted once the META_OPTIMIZER flag is removed.
Startup migration
A new useMcpOptimizerStartupCleanup hook runs at most once per session from RootComponent. It awaits electronAPI.isToolhiveRunning() (polling up to 60s) before marking itself as run, then invokes cleanupMetaOptimizer().
useCleanupMetaOptimizer is rewritten so the cleanup is self-contained and callable from outside a component. It fetches groups and the toolhive-mcp-optimizer workload at call-time via queryClient.fetchQuery, then:
If the meta-mcp workload has ALLOWED_GROUPS pointing at a user group that still exists, re-registers the optimizer-group clients to that target group.
Deletes the __mcp-optimizer__ group with ?with-workloads=true, taking the meta-mcp workload with it.
Cleanup is a no-op when the optimizer group doesn't exist, so users who never enabled the feature pay nothing at startup.
The cleanup path is intentionally the same teardown that used to run when the user flipped the experimental toggle off — nothing new is introduced, only relocated so it now fires automatically on first launch post-upgrade.
Acceptance criteria
/mcp-optimizer route, the sunset banner, and all optimizer-related UI affordances are gone.
On a profile with the optimizer previously enabled, launching the app removes the __mcp-optimizer__ group, re-registers its clients to whichever group was in ALLOWED_GROUPS, and tears down the meta-mcp workload — before any user interaction.
On a fresh profile with no optimizer state, the startup hook short-circuits after the daemon-ready wait and never writes to the API.
Relaunching the app is a no-op (the session flag short-circuits, and the group no longer exists either way).
No main-process changes beyond the feature-flag flip — cleanup runs entirely in the renderer against the public thv HTTP API, mirroring the experimental-toggle-off path.
Unit tests updated: use-cleanup-meta-optimizer.test.ts matches the call-time fetch model, flags.test.ts asserts isDisabled flags always return false, and the obsolete optimizer-specific permission-profile case is removed from orchestrate-run-local-server.test.tsx.
E2E coverage: e2e-tests/mcp-optimizer-startup-cleanup.spec.ts (backed by a reusable launchApp + thvFetch helper) runs two sessions against the same temporary userDataDir and asserts the optimizer group is gone, the client is re-registered to the custom group, and GET /workloads/toolhive-mcp-optimizer returns 404.
Goal
Remove the MCP Optimizer feature from the ToolHive Studio UI and ensure that users upgrading from a version where the optimizer was enabled are migrated cleanly on startup, so they don't end up with an orphaned
__mcp-optimizer__group, a danglingmeta-mcpworkload, or clients registered to a group that no longer has a UI surface.This follows #1910, which shipped the deprecation banner and prepared users for the sunset.
Why
The MCP Optimizer was an experimental feature that has been deprecated. Keeping the code, routes, hooks, and UI branches around adds maintenance cost, complicates the MCP servers / groups / clients flows with optimizer-specific branches, and leaves users who had previously enabled it in an inconsistent state after upgrade.
Scope
Remove from the product
/mcp-optimizer, the sunset banner (McpOptimizerSunsetBanner), the entirefeatures/meta-mcpmodule (group selector, loading dialog, optimizer warnings, and backing hooks).use-create-optimizer-group,use-optimize-group-name,use-is-optimized-group-name,use-mcp-optimizer-banner-visible,use-notification-optimizer, and their tests.toolhive-mcp-optimizerimage fromrenovate.json, dropMCP_OPTIMIZER_SUNSET_BLOG_URLfromcommon/app-info.ts, trimconstants.tsdown to the identifiers still needed by the cleanup migration.Keep for one release
META_OPTIMIZERremains in the feature-flag registry but set toisDisabled: true. It never shows up in experimental settings and always returnsfalse, but the key is preserved so the cleanup path can observe prior state. To be removed entirely in the next release.MCP_OPTIMIZER_GROUP_NAME/META_MCP_SERVER_NAMEconstants stay inconstants.tsbecause the cleanup hook depends on them. They can be inlined or deleted once theMETA_OPTIMIZERflag is removed.Startup migration
useMcpOptimizerStartupCleanuphook runs at most once per session fromRootComponent. It awaitselectronAPI.isToolhiveRunning()(polling up to 60s) before marking itself as run, then invokescleanupMetaOptimizer().useCleanupMetaOptimizeris rewritten so the cleanup is self-contained and callable from outside a component. It fetches groups and thetoolhive-mcp-optimizerworkload at call-time viaqueryClient.fetchQuery, then:ALLOWED_GROUPSpointing at a user group that still exists, re-registers the optimizer-group clients to that target group.__mcp-optimizer__group with?with-workloads=true, taking the meta-mcp workload with it.The cleanup path is intentionally the same teardown that used to run when the user flipped the experimental toggle off — nothing new is introduced, only relocated so it now fires automatically on first launch post-upgrade.
Acceptance criteria
/mcp-optimizerroute, the sunset banner, and all optimizer-related UI affordances are gone.__mcp-optimizer__group, re-registers its clients to whichever group was inALLOWED_GROUPS, and tears down the meta-mcp workload — before any user interaction.thvHTTP API, mirroring the experimental-toggle-off path.use-cleanup-meta-optimizer.test.tsmatches the call-time fetch model,flags.test.tsassertsisDisabledflags always returnfalse, and the obsolete optimizer-specific permission-profile case is removed fromorchestrate-run-local-server.test.tsx.e2e-tests/mcp-optimizer-startup-cleanup.spec.ts(backed by a reusablelaunchApp+thvFetchhelper) runs two sessions against the same temporaryuserDataDirand asserts the optimizer group is gone, the client is re-registered to the custom group, andGET /workloads/toolhive-mcp-optimizerreturns 404.References