Settings: MCP tool filtering, section merges, plugin/sidecar coupling - #155
Merged
Merged
Conversation
MCP_TOOL_IDS (useMcpToolEnabled.ts) is a static list that still names redis-client/kafka-explorer/rabbit-client/container-manager, even though those four moved from compiled-in tools to installable plugins. Both Settings → MCP and the "MCP for Claude Code" dialog (McpSetupDialog.tsx) mapped over that static list directly, so a toggle row for e.g. Kafka Explorer showed up (falling back to the bare id as its label, since it isn't in TOOL_DEFS) even when the plugin was never installed — flipping that toggle does nothing, since there's no plugin for it to gate. Fix: filter MCP_TOOL_IDS down to ids present in TOOL_DEFS (sourced from the registry, so it only lists plugins actually registered — core or currently installed) before rendering, in both places. Added Settings.mcpToolList.test.tsx, verified by temporarily reverting the filter in Settings.tsx and confirming the test fails for the right reason (the row renders using the bare id as a fallback label) before restoring it.
Reduces the left nav from 8 sections to 6, folding two single-purpose sections into the section they're most related to: - "Plugin" (SettingsPlugins.tsx: permissions read from each compiled-in tool's manifest, plus the activity/audit log) now renders under Tools, right below the enable/disable list — both are views onto the same set of tools, just answering different questions (what's on vs. what's it allowed to do vs. what has it actually done). - "Data & Storage" was a single row (data dir location + reveal-in-folder button) — folded into About as an extra card, not worth its own nav entry. Activity log changes (SettingsPlugins.tsx): - Collapsed by default behind a disclosure button showing the entry count — it can run up to 80 rows and isn't something most visits to this section need to see immediately. - Added a search box, filtered primarily by tool id but also matching channel/action/detail/missing-permission, so a keyword like a native command name or "denied" narrows it down too. Removed the now-unreferenced settings.plugins.title/settings.storage.title i18n keys (nav labels for the sections that no longer exist) and added auditShow/auditHide/auditSearchPlaceholder/auditNoMatch. Moved SettingsPlugins.test.tsx's audit-log assertions behind an openAuditLog() helper (log is closed by default now) and added tests for collapse-by-default and keyword filtering. Added Settings.mergedSections.test.tsx confirming both merges actually render in their new location and the old nav buttons are gone. Verified each new/changed assertion by temporarily reverting the corresponding code and confirming the test fails for the right reason, then restoring it — the collapse-by-default default and the Tools/Plugin merge were both checked this way.
A Tier B plugin (permissions: ['service']) and its native sidecar are installed as two separate artifact records — a plugin manifest and a service manifest, each with its own uninstall action in the Installed tab. Nothing tied them together: uninstalling the plugin left its sidecar running/installed with nothing left to call it, and uninstalling the sidecar left the plugin calling into a bin that no longer exists. Added findCoupledRecord(record, installed) (installer.ts): given one installed record, returns the other side of the pair — but only when the relationship is EXCLUSIVE (this plugin is the only one declaring that service.bin, and that service isn't relied on by any other installed plugin). A sidecar shared by multiple plugins, or a service installed on its own with nothing depending on it, comes back independent — gỡ one doesn't touch the other, matching how they were installed. SettingsInstalledExtensions.tsx now uses it for uninstall: - A plugin uninstall that has a coupled service goes through the same confirm-before-uninstall gate a service already required (it now indirectly stops a sidecar too), naming the exact counterpart that will also be removed. - Confirming cascades: both records are uninstalled, one busy/refresh cycle, one restart-needed banner. - The reverse direction works the same way — uninstalling the service side of a coupled pair also removes its dependent plugin. - A plugin with no service, a plugin whose service isn't installed, or a shared/standalone service — all uninstall independently exactly as before. Install-side coupling for the Marketplace/deep-link flow already existed (ExtensionInstallDialog installs a plugin's pluginManifestUrl + serviceManifestUrl together in one confirm). The one remaining gap was the plain "Install by URL" tab, which only ever sees one manifest URL at a time and has no way to fetch a second URL it was never given — SettingsExtensionInstaller.tsx now at least surfaces the gap: previewing a plugin manifest that declares a service dependency checks whether that service is already installed, and shows an inline warning naming the missing bin if not, instead of leaving it to a confusing runtime service-call error after install. Added findCoupledRecord tests (installer.test.ts) and cascading-uninstall tests (SettingsInstalledExtensions.test.tsx, both directions, plus shared/ standalone-stays-independent cases) and a preview-warning test (SettingsExtensionInstaller.test.tsx, both missing and already-installed cases). Verified each new behavior by temporarily reverting the corresponding code and confirming the test fails for the right reason, then restoring it.
|
This run was cancelled 🛑 The workflow was cancelled before completion. Please check the link below for details. |
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #155 +/- ##
==========================================
+ Coverage 42.11% 42.67% +0.56%
==========================================
Files 300 300
Lines 19874 19917 +43
Branches 4912 4933 +21
==========================================
+ Hits 8370 8500 +130
+ Misses 10508 10402 -106
- Partials 996 1015 +19
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
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.



Context
These three commits were originally pushed to
settings-extensions-installed-tab(PR #154), but #154 was merged after only its first commit ("Installed" tab) — the other three never made it into a PR and sat orphaned on that branch. This PR carries them forward, cherry-picked cleanly onto currentmain.Changes
Settings → MCP: only show per-tool toggle for tools actually registered
MCP_TOOL_IDSis a static list that still names redis-client/kafka-explorer/rabbit-client/container-manager even though those moved from compiled-in tools to installable plugins. Both Settings → MCP and the "MCP for Claude Code" dialog mapped over that static list directly, so a toggle row showed up (falling back to the bare id as its label) even when the plugin was never installed. Filtered both to only show tools actually registered (core or installed).Settings: merge Plugin into Tools, Data & Storage into About
Reduces the left nav from 8 sections to 6:
Extensions: couple a Tier B plugin's install/uninstall with its sidecar
A Tier B plugin and its native sidecar install as two separate artifact records with no relationship tracked between them — uninstalling one left the other orphaned. Added
findCoupledRecord(record, installed)(installer.ts): returns the paired record only when the relationship is exclusive (this plugin uniquely depends on that sidecar, and vice versa) — a shared sidecar or a standalone service stays independent. The Installed tab now cascades uninstall for a coupled pair (with confirmation naming the counterpart) in both directions, and the "Install by URL" tab warns in preview if a plugin declares a service dependency that isn't installed yet.Test plan
tsc --noEmitvitest run— 1399/1399 passing🤖 Generated with Claude Code
https://claude.ai/code/session_01BCypCuViyQDKGWxWspXKs2
Generated by Claude Code