Skip to content

fix: align Claude Code removeServer with plugin-based install path#491

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-claude-code-remove-server-mismatch
Draft

fix: align Claude Code removeServer with plugin-based install path#491
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-claude-code-remove-server-mismatch

Conversation

@posthog
Copy link
Copy Markdown

@posthog posthog Bot commented May 29, 2026

Problem

After commit 557ec08 introduced the Claude Code plugin install path, ClaudeCodeMCPClient ended up with a structural mismatch between its install check and its removal path:

  • isServerInstalled() (src/steps/add-mcp-server-to-clients/clients/claude-code.ts:91-93) delegates to isPluginInstalled(), which greps claude plugin list for posthog.
  • removeServer() only shelled out to claude mcp remove --scope user posthog.

Any user who installed PostHog via the plugin path without also registering a user-scoped MCP server is classified as "installed" by getInstalledClients(), but then the removal command fails with:

Command failed: claude mcp remove --scope user posthog
No user-scoped MCP server found with name: posthog

The error is wrapped via analytics.captureException and the wizard returns success: false for the Claude Code client. PostHog error tracking surfaced this as a new issue (fingerprint 19e2817…) on 2026-05-29 — currently 1 occurrence / 1 user, but it will reproduce for anyone on the plugin-only install path.

Changes

In claude-code.ts, removeServer() now mirrors the install path:

  1. If isPluginInstalled() is true, run claude plugin uninstall posthog.
  2. Independently, run claude mcp remove --scope user <serverName>.
  3. Both are best-effort. Benign error strings — No user-scoped MCP server found and plugin not-installed variants — are treated as no-ops. Only genuinely unexpected failures get reported via analytics.captureException.

The function returns success: true when nothing unexpected blew up, including the common case where one of the two surfaces simply has nothing to remove.

Test coverage added for:

  • plugin present + MCP absent (the bug scenario)
  • MCP present + plugin absent
  • local=true uses posthog-local
  • unexpected plugin uninstall failure
  • unexpected mcp remove failure
  • missing claude binary

Test plan

  • pnpm build
  • pnpm jest src/steps/add-mcp-server-to-clients/clients/__tests__/claude-code.test.ts — 16/16 pass
  • pnpm lint — no new errors
  • Full pnpm test — only an unrelated, pre-existing flaky timeout in src/__tests__/provision-cli.test.ts (passes in isolation, passes on main)

Created with PostHog Code

isServerInstalled() delegates to isPluginInstalled() (greps `claude plugin list`),
but removeServer() only shelled out to `claude mcp remove --scope user posthog`.
Any user who installed via the plugin path without also registering a user-scoped
MCP server would hit `No user-scoped MCP server found with name: posthog` during
uninstall, wrap it in a captured exception, and get `success: false`.

removeServer() now mirrors the install path: it first attempts
`claude plugin uninstall posthog` when isPluginInstalled() is true, then attempts
`claude mcp remove --scope user <serverName>` independently. Both are best-effort
— the known benign error strings ("No user-scoped MCP server found" and plugin
not-installed messages) are treated as no-ops, and only genuine unexpected
failures are reported to analytics.captureException.

Adds removeServer test coverage for plugin-present + MCP-absent and
MCP-present + plugin-absent, plus unexpected-failure and binary-missing paths.

Generated-By: PostHog Code
Task-Id: 2f489aa4-8bf6-424d-b112-22bc9b814a63
@github-actions
Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci basic-integration
  • /wizard-ci misc
  • /wizard-ci revenue

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci misc/quack-quack
  • /wizard-ci revenue/stripe

Results will be posted here when complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants