@posthog/wizard 2.70.1 → 2.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/{add-mcp-server-to-clients-BCnjUqnW.js → add-mcp-server-to-clients-B6-ZL--P.js} +4 -4
  2. package/dist/{add-mcp-server-to-clients-BCnjUqnW.js.map → add-mcp-server-to-clients-B6-ZL--P.js.map} +1 -1
  3. package/dist/{agent-interface-Lu7tnLr0.js → agent-interface-DFm4jB4d.js} +108 -15
  4. package/dist/agent-interface-DFm4jB4d.js.map +1 -0
  5. package/dist/{agent-prompt-loader-y5GxgEkc.js → agent-prompt-loader-Bi3IzSBW.js} +5 -5
  6. package/dist/{agent-prompt-loader-y5GxgEkc.js.map → agent-prompt-loader-Bi3IzSBW.js.map} +1 -1
  7. package/dist/{agent-runner-vKtpgqVI.js → agent-runner-Cp6iLqDk.js} +49 -16
  8. package/dist/agent-runner-Cp6iLqDk.js.map +1 -0
  9. package/dist/{analytics-DTyJClPr.js → analytics-D54mLptm.js} +3 -3
  10. package/dist/{analytics-DTyJClPr.js.map → analytics-D54mLptm.js.map} +1 -1
  11. package/dist/analytics-Ge1LsCNg.js +2 -0
  12. package/dist/{api-j-OfJ8Dz.js → api-BNBVOguz.js} +23 -4
  13. package/dist/{api-j-OfJ8Dz.js.map → api-BNBVOguz.js.map} +1 -1
  14. package/dist/bin.js +79 -73
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{bounded-fs-BWX25ixc.js → bounded-fs-DHIaH3Sc.js} +3 -3
  17. package/dist/{bounded-fs-BWX25ixc.js.map → bounded-fs-DHIaH3Sc.js.map} +1 -1
  18. package/dist/{ci-install-zNWgp1TL.js → ci-install-Can8LRdJ.js} +5 -5
  19. package/dist/{ci-install-zNWgp1TL.js.map → ci-install-Can8LRdJ.js.map} +1 -1
  20. package/dist/{debug-xr2Pq5VA.js → debug-C4RPcEIX.js} +1 -1
  21. package/dist/{debug-BM0fZaGl.js → debug-YQdeZulR.js} +4 -3
  22. package/dist/debug-YQdeZulR.js.map +1 -0
  23. package/dist/{env-api-key-DlxCZWU0.js → env-api-key-9yogO8OI.js} +2 -2
  24. package/dist/{env-api-key-DlxCZWU0.js.map → env-api-key-9yogO8OI.js.map} +1 -1
  25. package/dist/{environment-o-bTOuzK.js → environment-6ZuAWRpQ.js} +4 -4
  26. package/dist/{environment-o-bTOuzK.js.map → environment-6ZuAWRpQ.js.map} +1 -1
  27. package/dist/{errors-BSdz2lsl.js → errors-u8z27V-x.js} +4 -2
  28. package/dist/errors-u8z27V-x.js.map +1 -0
  29. package/dist/{file-watcher-D7G4f5sP.js → file-watcher-CeWdvMVT.js} +2 -2
  30. package/dist/{file-watcher-D7G4f5sP.js.map → file-watcher-CeWdvMVT.js.map} +1 -1
  31. package/dist/{headless-ui-C46DctKG.js → headless-ui-BxSVgNoT.js} +2 -2
  32. package/dist/{headless-ui-C46DctKG.js.map → headless-ui-BxSVgNoT.js.map} +1 -1
  33. package/dist/{interactive-B5zy3Gxk.js → interactive-CRR9zPl4.js} +2 -2
  34. package/dist/{interactive-B5zy3Gxk.js.map → interactive-CRR9zPl4.js.map} +1 -1
  35. package/dist/{mcp-lJRwE-YW.js → mcp-D_rRzruj.js} +2 -2
  36. package/dist/{mcp-lJRwE-YW.js.map → mcp-D_rRzruj.js.map} +1 -1
  37. package/dist/{mcp-prompt-streaming-Dsos09hT.js → mcp-prompt-streaming-DRAK8CMP.js} +5 -4
  38. package/dist/mcp-prompt-streaming-DRAK8CMP.js.map +1 -0
  39. package/dist/{non-interactive-qcCCtiYQ.js → non-interactive-1EJRlN6u.js} +3 -3
  40. package/dist/{non-interactive-qcCCtiYQ.js.map → non-interactive-1EJRlN6u.js.map} +1 -1
  41. package/dist/{orchestrator-tools-ezFTbAIp.js → orchestrator-tools-DjZWqWmd.js} +3 -3
  42. package/dist/{orchestrator-tools-ezFTbAIp.js.map → orchestrator-tools-DjZWqWmd.js.map} +1 -1
  43. package/dist/{package-manager-CGfN9UhH.js → package-manager-DMbzbdkL.js} +2 -2
  44. package/dist/{package-manager-CGfN9UhH.js.map → package-manager-DMbzbdkL.js.map} +1 -1
  45. package/dist/{pi-DzQLHIcQ.js → pi-D4JQMC-7.js} +18 -15
  46. package/dist/pi-D4JQMC-7.js.map +1 -0
  47. package/dist/{playground-DLN31BPV.js → playground-Y1nSGXpn.js} +43 -8
  48. package/dist/playground-Y1nSGXpn.js.map +1 -0
  49. package/dist/{posthog-Dxr8XK4x.js → posthog-D9VwcWvJ.js} +2 -2
  50. package/dist/{posthog-Dxr8XK4x.js.map → posthog-D9VwcWvJ.js.map} +1 -1
  51. package/dist/{posthog-integration-MDfRO911.js → posthog-integration-B8f4xRBd.js} +18 -18
  52. package/dist/posthog-integration-B8f4xRBd.js.map +1 -0
  53. package/dist/{provisioning-Di5GNV9k.js → provisioning-f7lA29tW.js} +14 -5
  54. package/dist/provisioning-f7lA29tW.js.map +1 -0
  55. package/dist/{queue-tools-KosDptd6.js → queue-tools-DGaHf3n-.js} +3 -3
  56. package/dist/{queue-tools-KosDptd6.js.map → queue-tools-DGaHf3n-.js.map} +1 -1
  57. package/dist/{registry-BBdaIFWq.js → registry-D1By1SgH.js} +5 -5
  58. package/dist/{registry-BBdaIFWq.js.map → registry-D1By1SgH.js.map} +1 -1
  59. package/dist/{security-BwOvjMaq.js → security-C2c3_Ycy.js} +5 -5
  60. package/dist/{security-BwOvjMaq.js.map → security-C2c3_Ycy.js.map} +1 -1
  61. package/dist/{setup-utils-Bo3WZt3a.js → setup-utils-BRrCeajl.js} +42 -11
  62. package/dist/setup-utils-BRrCeajl.js.map +1 -0
  63. package/dist/{start-tui-B1LrB7k1.js → start-tui-r4Spgptv.js} +257 -23
  64. package/dist/start-tui-r4Spgptv.js.map +1 -0
  65. package/dist/{steps-BMrQJpQh.js → steps-BZd65XfI.js} +7 -7
  66. package/dist/{steps-BMrQJpQh.js.map → steps-BZd65XfI.js.map} +1 -1
  67. package/dist/{store-DhNTBWQR.js → store-DGVXu7xt.js} +25 -6
  68. package/dist/store-DGVXu7xt.js.map +1 -0
  69. package/dist/{subagent-q6M-mBHo.js → subagent-BaMxO7OT.js} +2 -2
  70. package/dist/{subagent-q6M-mBHo.js.map → subagent-BaMxO7OT.js.map} +1 -1
  71. package/dist/{task-CgAOxod7.js → task-DpKoEZ5I.js} +13 -13
  72. package/dist/{task-CgAOxod7.js.map → task-DpKoEZ5I.js.map} +1 -1
  73. package/dist/{task-stream-rxR1IsdJ.js → task-stream-CdrBraqP.js} +6 -6
  74. package/dist/{task-stream-rxR1IsdJ.js.map → task-stream-CdrBraqP.js.map} +1 -1
  75. package/dist/{tasks-lzvWF__k.js → tasks-KsP66Cis.js} +2 -2
  76. package/dist/{tasks-lzvWF__k.js.map → tasks-KsP66Cis.js.map} +1 -1
  77. package/dist/{telemetry-CickTk_7.js → telemetry-DedDTtSa.js} +3 -3
  78. package/dist/{telemetry-CickTk_7.js.map → telemetry-DedDTtSa.js.map} +1 -1
  79. package/dist/{terminal-BjUFxn_x.js → terminal-BH8yLclG.js} +107 -61
  80. package/dist/terminal-BH8yLclG.js.map +1 -0
  81. package/dist/{tools-MKXGXFSk.js → tools-CJw5vnZd.js} +6 -6
  82. package/dist/{tools-MKXGXFSk.js.map → tools-CJw5vnZd.js.map} +1 -1
  83. package/dist/{wizard-abort-CooWEh9N.js → wizard-abort-D54j2gmb.js} +5 -5
  84. package/dist/{wizard-abort-CooWEh9N.js.map → wizard-abort-D54j2gmb.js.map} +1 -1
  85. package/dist/{wizard-abort-CW_C2EXr.js → wizard-abort-Q1NiYELE.js} +1 -1
  86. package/dist/{wizard-session-Bki7dQhv.js → wizard-session-CwQPZN4y.js} +3 -1
  87. package/dist/wizard-session-CwQPZN4y.js.map +1 -0
  88. package/dist/{wizard-session-gbYCXdBf.js → wizard-session-Dwc1Rh_7.js} +1 -1
  89. package/dist/yara-hooks-BI6WY0Sl.js +2 -0
  90. package/dist/{yara-hooks-BpngckdZ.js → yara-hooks-CL2LVEgO.js} +4 -4
  91. package/dist/{yara-hooks-BpngckdZ.js.map → yara-hooks-CL2LVEgO.js.map} +1 -1
  92. package/package.json +1 -1
  93. package/dist/agent-interface-Lu7tnLr0.js.map +0 -1
  94. package/dist/agent-runner-vKtpgqVI.js.map +0 -1
  95. package/dist/analytics-D-bMEYjD.js +0 -2
  96. package/dist/debug-BM0fZaGl.js.map +0 -1
  97. package/dist/errors-BSdz2lsl.js.map +0 -1
  98. package/dist/mcp-prompt-streaming-Dsos09hT.js.map +0 -1
  99. package/dist/pi-DzQLHIcQ.js.map +0 -1
  100. package/dist/playground-DLN31BPV.js.map +0 -1
  101. package/dist/posthog-integration-MDfRO911.js.map +0 -1
  102. package/dist/provisioning-Di5GNV9k.js.map +0 -1
  103. package/dist/setup-utils-Bo3WZt3a.js.map +0 -1
  104. package/dist/start-tui-B1LrB7k1.js.map +0 -1
  105. package/dist/store-DhNTBWQR.js.map +0 -1
  106. package/dist/terminal-BjUFxn_x.js.map +0 -1
  107. package/dist/wizard-session-Bki7dQhv.js.map +0 -1
  108. package/dist/yara-hooks-C-qG6EJt.js +0 -2
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
2
- import { f as getUI, r as debug, xt as runtimeEnv } from "./debug-BM0fZaGl.js";
3
- import { n as analytics } from "./analytics-DTyJClPr.js";
4
- import { n as openTrackedLink, t as withProgress } from "./telemetry-CickTk_7.js";
2
+ import { f as getUI, r as debug, xt as runtimeEnv } from "./debug-YQdeZulR.js";
3
+ import { n as analytics } from "./analytics-D54mLptm.js";
4
+ import { n as openTrackedLink, t as withProgress } from "./telemetry-DedDTtSa.js";
5
5
  import { a as getNativeHTTPServerConfig, c as namesWithStatus, d as toClientResult, i as getDefaultServerConfig, l as redactSecrets, r as buildMCPUrl, t as ALL_FEATURE_VALUES } from "./defaults-DI642M3n.js";
6
6
  import * as fs$2 from "fs";
7
7
  import * as path$3 from "path";
@@ -900,4 +900,4 @@ const removeMCPServer = async (clients, local) => {
900
900
  //#endregion
901
901
  export { getSupportedClients as a, removeMCPServer as c, getInstalledClients as i, removeMCPServerFromClientsStep as l, addMCPServerToClientsStep as n, getSupportedPluginClients as o, add_mcp_server_to_clients_exports as r, installPlugins as s, addMCPServer as t, isPluginCapable as u };
902
902
 
903
- //# sourceMappingURL=add-mcp-server-to-clients-BCnjUqnW.js.map
903
+ //# sourceMappingURL=add-mcp-server-to-clients-B6-ZL--P.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"add-mcp-server-to-clients-BCnjUqnW.js","names":["fs","path","path","os","path","os","fs","execSync","z","os","path","z","os","path","path","fs","z","path","fs","os"],"sources":["../src/steps/add-mcp-server-to-clients/MCPClient.ts","../src/steps/add-mcp-server-to-clients/clients/cursor.ts","../src/steps/add-mcp-server-to-clients/clients/claude-code.ts","../src/steps/add-mcp-server-to-clients/clients/claude-web.ts","../src/steps/add-mcp-server-to-clients/clients/visual-studio-code.ts","../src/steps/add-mcp-server-to-clients/clients/zed.ts","../src/steps/add-mcp-server-to-clients/clients/codex.ts","../src/steps/add-mcp-server-to-clients/clients/opencode.ts","../src/steps/add-mcp-server-to-clients/plugin-client.ts","../src/steps/add-mcp-server-to-clients/index.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as jsonc from 'jsonc-parser';\nimport { getDefaultServerConfig } from './defaults';\nimport type { InstallResult } from './results';\n\nexport type MCPServerConfig = Record<string, unknown>;\n\nexport abstract class MCPClient {\n name: string;\n abstract getConfigPath(): Promise<string>;\n abstract getServerPropertyName(): string;\n abstract isServerInstalled(local?: boolean): Promise<boolean>;\n abstract addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult>;\n abstract removeServer(local?: boolean): Promise<InstallResult>;\n abstract isClientSupported(): Promise<boolean>;\n}\n\nexport abstract class DefaultMCPClient extends MCPClient {\n name = 'Default';\n\n constructor() {\n super();\n }\n\n getServerPropertyName(): string {\n return 'mcpServers';\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getDefaultServerConfig(apiKey, selectedFeatures, local);\n }\n\n async isServerInstalled(local?: boolean): Promise<boolean> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return false;\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n const serverName = local ? 'posthog-local' : 'posthog';\n\n return (\n serverPropertyName in config && serverName in config[serverPropertyName]\n );\n } catch {\n return false;\n }\n }\n\n async addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n try {\n const configPath = await this.getConfigPath();\n const configDir = path.dirname(configPath);\n\n await fs.promises.mkdir(configDir, { recursive: true });\n\n const serverPropertyName = this.getServerPropertyName();\n let configContent = '';\n let existingConfig = {};\n\n if (fs.existsSync(configPath)) {\n configContent = await fs.promises.readFile(configPath, 'utf8');\n existingConfig = jsonc.parse(configContent) || {};\n }\n\n const newServerConfig = this.getServerConfig(\n apiKey,\n selectedFeatures,\n local,\n );\n const typedConfig = existingConfig as Record<string, any>;\n if (!typedConfig[serverPropertyName]) {\n typedConfig[serverPropertyName] = {};\n }\n const serverName = local ? 'posthog-local' : 'posthog';\n\n // An identical entry means this config is already set up — leave the file\n // untouched and report it, so a re-run says \"already installed\" instead of\n // claiming a write that changed nothing. A differing entry (new features,\n // new key) still gets overwritten and reported as installed.\n const existingServerConfig = typedConfig[serverPropertyName][serverName];\n if (\n existingServerConfig !== undefined &&\n JSON.stringify(existingServerConfig) === JSON.stringify(newServerConfig)\n ) {\n return { success: true, alreadyInstalled: true };\n }\n\n typedConfig[serverPropertyName][serverName] = newServerConfig;\n\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n newServerConfig,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async removeServer(local?: boolean): Promise<InstallResult> {\n let configPath = '';\n try {\n configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return { success: true, alreadyInstalled: true };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n\n const serverName = local ? 'posthog-local' : 'posthog';\n\n if (\n serverPropertyName in config &&\n serverName in config[serverPropertyName]\n ) {\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n undefined,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n }\n // No PostHog entry to delete — the config changed under us between the\n // detection pass and now. Nothing failed, so don't report a failure.\n return { success: true, alreadyInstalled: true };\n } catch (error) {\n return {\n success: false,\n reason: `${configPath}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n };\n }\n }\n}\n","import {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClientConfig,\n getNativeHTTPServerConfig,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport { z } from 'zod';\n\nexport const CursorMCPConfig = DefaultMCPClientConfig;\n\nexport type CursorMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CursorMCPClient extends DefaultMCPClient {\n name = 'Cursor';\n\n constructor() {\n super();\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'win32',\n );\n }\n\n async getConfigPath(): Promise<string> {\n return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getNativeHTTPServerConfig(apiKey, selectedFeatures, local);\n }\n}\n","import { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport {\n DefaultMCPClientConfig,\n buildMCPUrl,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\nimport {\n redactSecrets,\n type InstallResult,\n} from '@steps/add-mcp-server-to-clients/results';\nimport { LoginCapable } from '@steps/add-mcp-server-to-clients/login-client';\nimport { z } from 'zod';\nimport { execSync } from 'child_process';\nimport { analytics } from '@utils/analytics';\nimport { debug } from '@utils/debug';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport const ClaudeCodeMCPConfig = DefaultMCPClientConfig;\n\nexport type ClaudeCodeMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class ClaudeCodeMCPClient\n extends DefaultMCPClient\n implements PluginCapable, LoginCapable\n{\n name = 'Claude Code';\n private claudeBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findClaudeBinary(): string | null {\n if (this.claudeBinaryPath) {\n return this.claudeBinaryPath;\n }\n\n // Common installation paths for Claude Code CLI\n const possiblePaths = [\n path.join(os.homedir(), '.claude', 'local', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\n for (const claudePath of possiblePaths) {\n if (fs.existsSync(claudePath)) {\n debug(` Found claude binary at: ${claudePath}`);\n this.claudeBinaryPath = claudePath;\n return claudePath;\n }\n }\n\n // Try PATH as fallback\n try {\n execSync('command -v claude', { stdio: 'pipe' });\n debug(' Found claude in PATH');\n this.claudeBinaryPath = 'claude';\n return 'claude';\n } catch {\n // Not in PATH\n }\n\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n try {\n debug(' Checking for Claude Code...');\n const claudeBinary = this.findClaudeBinary();\n\n if (!claudeBinary) {\n debug(' Claude Code not found. Installation paths checked:');\n debug(` - ${path.join(os.homedir(), '.claude', 'local', 'claude')}`);\n debug(` - /usr/local/bin/claude`);\n debug(` - /opt/homebrew/bin/claude`);\n debug(` - PATH`);\n return Promise.resolve(false);\n }\n\n const output = execSync(`${claudeBinary} --version`, { stdio: 'pipe' });\n const version = output.toString().trim();\n debug(` Claude Code detected: ${version}`);\n return Promise.resolve(true);\n } catch (error) {\n debug(\n ` Claude Code check failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return Promise.resolve(false);\n }\n }\n\n isServerInstalled(local?: boolean): Promise<boolean> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve(false);\n const serverName = local ? 'posthog-local' : 'posthog';\n // `mcp get <name>` exits non-zero when the entry doesn't exist. A substring\n // scan of `mcp list` also matches the claude.ai \"PostHog\" connector and the\n // plugin's `plugin:posthog:posthog`, reporting installed forever.\n try {\n execSync(`${binary} mcp get ${serverName}`, { stdio: 'pipe' });\n return Promise.resolve(true);\n } catch {\n return Promise.resolve(false);\n }\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n });\n\n const serverName = local ? 'posthog-local' : 'posthog';\n const url = buildMCPUrl(selectedFeatures, local);\n const args = [\n 'mcp',\n 'add',\n '--transport',\n 'http',\n '--scope',\n 'user',\n serverName,\n url,\n ];\n if (apiKey) {\n args.push('--header', `Authorization: Bearer ${apiKey}`);\n }\n\n try {\n execSync(`${binary} ${args.map((a) => JSON.stringify(a)).join(' ')}`, {\n stdio: 'pipe',\n });\n return Promise.resolve({ success: true });\n } catch (error) {\n // The failing command echoes back the Authorization header we passed, so\n // redact before this reaches a log, the screen, or an exception report.\n const msg = redactSecrets(\n error instanceof Error ? error.message : String(error),\n );\n if (msg.includes('already exists')) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n analytics.captureException(\n new Error(`Claude Code MCP add failed: ${msg}`),\n );\n return Promise.resolve({ success: false, reason: msg });\n }\n }\n\n /** Claude Code's own login runs its OAuth and owns the token; the wizard only surfaces the command. */\n loginCommand(local?: boolean): string {\n return `claude mcp login ${local ? 'posthog-local' : 'posthog'}`;\n }\n\n /** The plugin bundles its own `posthog` server, addressed as `plugin:<plugin>:<server>`. */\n pluginLoginCommand(): string {\n return 'claude mcp login plugin:posthog:posthog';\n }\n\n async removePlugin(): Promise<PluginInstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n };\n\n if (!(await this.isPluginInstalled())) {\n return { success: true, alreadyInstalled: true };\n }\n\n try {\n execSync(`${binary} plugin uninstall posthog`, { stdio: 'pipe' });\n return { success: true };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n analytics.captureException(\n new Error(`Claude Code plugin uninstall failed: ${msg}`),\n );\n return { success: false, reason: msg };\n }\n }\n\n removeServer(local?: boolean): Promise<InstallResult> {\n const claudeBinary = this.findClaudeBinary();\n if (!claudeBinary) {\n return Promise.resolve({\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n });\n }\n\n const serverName = local ? 'posthog-local' : 'posthog';\n const command = `${claudeBinary} mcp remove --scope user ${serverName}`;\n\n try {\n execSync(command, { stdio: 'pipe' });\n } catch (error) {\n const reason = redactSecrets(\n error instanceof Error ? error.message : String(error),\n );\n // Removing something that isn't there is the requested end state, not a\n // failure to report.\n if (/no( such)? mcp server|not found/i.test(reason)) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n analytics.captureException(\n new Error(`Failed to remove server from Claude Code: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n\n return Promise.resolve({ success: true });\n }\n\n /** The plugin ships mcp.json with the posthog server — no direct entry needed. */\n pluginBundlesMcpServer(): boolean {\n return true;\n }\n\n supportsPlugin(): boolean {\n return this.findClaudeBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve(false);\n try {\n const output = execSync(`${binary} plugin list`, {\n stdio: 'pipe',\n }).toString();\n return Promise.resolve(output.toLowerCase().includes('posthog'));\n } catch {\n return Promise.resolve(false);\n }\n }\n\n async installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n };\n\n // Ask before installing so a re-run reports \"already installed\" rather than\n // relying on the CLI's error text to spot the no-op.\n if (await this.isPluginInstalled()) {\n return { success: true, alreadyInstalled: true };\n }\n\n try {\n execSync(`${binary} plugin install posthog`, { stdio: 'pipe' });\n return { success: true };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('already installed') || msg.includes('already exists')) {\n return { success: true, alreadyInstalled: true };\n }\n analytics.captureException(\n new Error(`Claude Code plugin install failed: ${msg}`),\n );\n return { success: false, reason: msg };\n }\n }\n}\n","import { MCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport type { InstallResult } from '@steps/add-mcp-server-to-clients/results';\nimport { BrowserFinishable } from '@steps/add-mcp-server-to-clients/browser-client';\nimport { openTrackedLink } from '@utils/links';\n\n/**\n * Claude Desktop / Claude.ai (web). PostHog ships here as a hosted connector,\n * not a local config — so instead of writing files we open the connector\n * directory page and let the user sign in and click \"Connect\".\n */\nexport class ClaudeWebMCPClient extends MCPClient implements BrowserFinishable {\n name = 'Claude Desktop/Web';\n connectorUrl = 'https://claude.ai/directory/connectors/posthog';\n finishInstruction = 'Sign in and click \"Connect\" to finish.';\n\n isClientSupported(): Promise<boolean> {\n // Browser-based — available on every platform.\n return Promise.resolve(true);\n }\n\n isServerInstalled(): Promise<boolean> {\n // The connector lives in the user's Claude account; nothing local to\n // inspect. Returning false also keeps it out of `mcp remove`.\n return Promise.resolve(false);\n }\n\n addServer(): Promise<InstallResult> {\n // Not a PostHog property, so no UTMs — just the tracked open.\n openTrackedLink(this.connectorUrl, 'claude-web-connector', {\n auto: true,\n skipUtm: true,\n });\n return Promise.resolve({ success: true });\n }\n\n removeServer(): Promise<InstallResult> {\n // The connector lives in the user's Claude account, so `mcp remove` can't\n // touch it. It never reaches here today (isServerInstalled is always\n // false), but say where to go if it ever does.\n return Promise.resolve({\n success: false,\n reason:\n 'This connector is managed in your Claude account — remove it at claude.ai/settings/connectors.',\n });\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n getServerPropertyName(): string {\n throw new Error('Not implemented');\n }\n}\n\nexport default ClaudeWebMCPClient;\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const VisualStudioCodeMCPConfig = z\n .object({\n servers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n type: z.enum(['http', 'sse']),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type VisualStudioCodeMCPConfig = z.infer<\n typeof VisualStudioCodeMCPConfig\n>;\n\nexport class VisualStudioCodeClient extends DefaultMCPClient {\n name = 'Visual Studio Code';\n\n getServerPropertyName(): string {\n return 'servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' ||\n process.platform === 'win32' ||\n process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isWindows = process.platform === 'win32';\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(\n homeDir,\n 'Library',\n 'Application Support',\n 'Code',\n 'User',\n 'mcp.json',\n ),\n );\n }\n\n if (isWindows) {\n return Promise.resolve(\n path.join(runtimeEnv('APPDATA') || '', 'Code', 'User', 'mcp.json'),\n );\n }\n\n if (isLinux) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'Code', 'User', 'mcp.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n type: 'http',\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const ZedMCPConfig = z\n .object({\n context_servers: z.record(\n z.string(),\n z.union([\n z.object({\n enabled: z.boolean().optional(),\n source: z.string().optional(),\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n enabled: z.boolean().optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type ZedMCPConfig = z.infer<typeof ZedMCPConfig>;\n\nexport class ZedClient extends DefaultMCPClient {\n name = 'Zed';\n\n getServerPropertyName(): string {\n return 'context_servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n if (isLinux) {\n // https://zed.dev/docs/configuring-zed#settings-files\n const xdgConfigHome = runtimeEnv('XDG_CONFIG_HOME');\n if (xdgConfigHome) {\n return Promise.resolve(\n path.join(xdgConfigHome, 'zed', 'settings.json'),\n );\n }\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n enabled: true,\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import { z } from 'zod';\nimport { execSync, spawnSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nimport { LoginCapable } from '@steps/add-mcp-server-to-clients/login-client';\nimport { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport {\n DefaultMCPClientConfig,\n buildMCPUrl,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\nimport {\n redactSecrets,\n type InstallResult,\n} from '@steps/add-mcp-server-to-clients/results';\n\nimport { analytics } from '@utils/analytics';\n\n/** Wording codex uses when the thing we're adding is already registered. */\nconst ALREADY_INSTALLED_PATTERN =\n /already (installed|exists|added|registered)/i;\n/** Wording that means the opposite: a cache entry exists but the plugin doesn't. */\nconst STALE_MARKETPLACE_CACHE = /already added from a different source/i;\n\n/**\n * Codex allows servers 10s to finish the MCP initialize handshake, and a remote\n * OAuth handshake can exceed that on a cold start — the \"servers were not\n * initialized\" warning.\n */\nconst STARTUP_TIMEOUT_SEC = 30;\n\n/**\n * The server's table header. TOML accepts a bare or quoted key for the same\n * table, and matching only the bare form means we append a second definition of\n * a table that already exists — a duplicate-key error that takes the user's\n * whole config down, not just PostHog's entry.\n */\nconst sectionHeader = (serverName: string): RegExp =>\n new RegExp(\n `^\\\\[mcp_servers\\\\.(?:${serverName}|\"${serverName}\")\\\\][ \\\\t]*$`,\n 'm',\n );\n\n/**\n * Set `key = value` inside a section body, inserting it when absent. Scans the\n * whole body rather than the line after the header: TOML does not care about\n * key order, and assuming it does means silently matching nothing.\n */\nconst setKey = (body: string, key: string, value: string): string => {\n const existing = new RegExp(`^[ \\\\t]*${key}[ \\\\t]*=.*$`, 'm');\n return existing.test(body)\n ? body.replace(existing, `${key} = ${value}`)\n : `\\n${key} = ${value}${body}`;\n};\n\nexport const CodexMCPConfig = DefaultMCPClientConfig;\n\nexport type CodexMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CodexMCPClient\n extends DefaultMCPClient\n implements PluginCapable, LoginCapable\n{\n name = 'Codex';\n private codexBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findCodexBinary(): string | null {\n if (this.codexBinaryPath) return this.codexBinaryPath;\n try {\n const resolved = execSync('command -v codex', { stdio: 'pipe' })\n .toString()\n .trim();\n if (resolved) {\n this.codexBinaryPath = resolved;\n return resolved;\n }\n } catch {\n // not in PATH\n }\n return null;\n }\n\n private configPath(): string {\n return path.join(os.homedir(), '.codex', 'config.toml');\n }\n\n isClientSupported(): Promise<boolean> {\n return Promise.resolve(this.findCodexBinary() !== null);\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n isServerInstalled(local?: boolean): Promise<boolean> {\n const serverName = local ? 'posthog-local' : 'posthog';\n // The `[mcp_servers.<name>]` section in config.toml — both the CLI and the\n // desktop app read (and `codex mcp add` writes) this file, and a substring\n // scan of `mcp list` matches unrelated posthog-ish servers.\n try {\n const contents = fs.readFileSync(this.configPath(), 'utf-8');\n return Promise.resolve(sectionHeader(serverName).test(contents));\n } catch {\n return Promise.resolve(false);\n }\n }\n\n addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n const serverName = local ? 'posthog-local' : 'posthog';\n const url = buildMCPUrl(selectedFeatures, local);\n\n // Api-key installs go through the CLI for its bearer-token env wiring.\n if (apiKey) {\n const binary = this.findCodexBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'An API-key install into Codex needs the codex CLI.',\n });\n const args = [\n 'mcp',\n 'add',\n serverName,\n '--url',\n url,\n '--bearer-token-env-var',\n 'POSTHOG_AUTH_HEADER',\n ];\n const env = { ...process.env, POSTHOG_AUTH_HEADER: `Bearer ${apiKey}` };\n const result = spawnSync(binary, args, { encoding: 'utf-8', env });\n if (result.status !== 0) {\n const stderr = result.stderr ?? '';\n if (ALREADY_INSTALLED_PATTERN.test(stderr)) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n const reason = redactSecrets(stderr);\n analytics.captureException(\n new Error(`Codex MCP add failed: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n return Promise.resolve({ success: true });\n }\n\n // OAuth installs write config.toml directly: running `codex mcp add` here\n // would hang the wizard on its built-in OAuth browser wait. Codex nags\n // about the unauthenticated server until the surfaced `codex mcp login`\n // runs — the same interim state as Claude Code's \"needs authentication\".\n return Promise.resolve(this.writeServerSection(serverName, url));\n }\n\n /**\n * Create or update the `[mcp_servers.<name>]` section in config.toml, editing\n * in place so the user's other servers, key order, and comments survive.\n */\n private writeServerSection(serverName: string, url: string): InstallResult {\n const configPath = this.configPath();\n try {\n // A machine that has codex installed but has never run it has no\n // ~/.codex at all — `codex mcp add` used to create it for us.\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n const contents = fs.existsSync(configPath)\n ? fs.readFileSync(configPath, 'utf-8')\n : '';\n\n const header = sectionHeader(serverName).exec(contents);\n if (!header) {\n const gap = contents === '' || contents.endsWith('\\n\\n') ? '' : '\\n';\n const pad = contents === '' || contents.endsWith('\\n') ? '' : '\\n';\n this.write(\n configPath,\n `${contents}${pad}${gap}[mcp_servers.${serverName}]\\n` +\n `url = \"${url}\"\\nstartup_timeout_sec = ${STARTUP_TIMEOUT_SEC}\\n`,\n );\n return { success: true };\n }\n\n // Everything up to the next table header belongs to this server.\n const start = header.index + header[0].length;\n const rest = contents.slice(start);\n const next = /^\\[/m.exec(rest);\n const end = next ? start + next.index : contents.length;\n\n const body = contents.slice(start, end);\n const updated = setKey(\n setKey(body, 'url', `\"${url}\"`),\n 'startup_timeout_sec',\n String(STARTUP_TIMEOUT_SEC),\n );\n if (updated === body) return { success: true, alreadyInstalled: true };\n\n this.write(\n configPath,\n contents.slice(0, start) + updated + contents.slice(end),\n );\n return { success: true };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n analytics.captureException(\n new Error(`Codex config.toml write failed: ${reason}`),\n );\n return { success: false, reason };\n }\n }\n\n /** Write via a sibling temp file: a crash mid-write must not truncate the config. */\n private write(configPath: string, contents: string): void {\n const tmp = `${configPath}.wizard-tmp`;\n fs.writeFileSync(tmp, contents);\n fs.renameSync(tmp, configPath);\n }\n\n /** Codex's own login runs its OAuth and owns the token; the wizard only surfaces the command. */\n loginCommand(local?: boolean): string | null {\n if (!this.findCodexBinary()) return null;\n return `codex mcp login ${local ? 'posthog-local' : 'posthog'}`;\n }\n\n removeServer(local?: boolean): Promise<InstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n });\n\n // `local` was ignored here, so `mcp remove --local` reported success while\n // leaving the posthog-local server in place.\n const serverName = local ? 'posthog-local' : 'posthog';\n const result = spawnSync(binary, ['mcp', 'remove', serverName], {\n encoding: 'utf-8',\n });\n\n if (result.error || result.status !== 0) {\n const reason = redactSecrets(\n result.error?.message ?? result.stderr ?? 'codex mcp remove failed',\n );\n analytics.captureException(\n new Error(`Failed to remove server from Codex CLI: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n\n return Promise.resolve({ success: true });\n }\n\n /** The codex marketplace plugin ships skills only — the MCP server needs its own entry. */\n pluginBundlesMcpServer(): boolean {\n return false;\n }\n\n supportsPlugin(): boolean {\n return this.findCodexBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const configPath = path.join(os.homedir(), '.codex', 'config.toml');\n try {\n const contents = fs.readFileSync(configPath, 'utf-8');\n // Marketplace installs appear as [marketplaces.posthog] in config.toml\n return Promise.resolve(\n contents.toLowerCase().includes('[marketplaces.posthog]'),\n );\n } catch {\n return Promise.resolve(false);\n }\n }\n\n async removePlugin(): Promise<PluginInstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n };\n\n if (!(await this.isPluginInstalled())) {\n return { success: true, alreadyInstalled: true };\n }\n\n const result = spawnSync(\n binary,\n ['plugin', 'marketplace', 'remove', 'posthog'],\n { encoding: 'utf-8' },\n );\n if (result.status !== 0) {\n const reason = redactSecrets(\n result.stderr ?? 'codex plugin marketplace remove failed',\n );\n analytics.captureException(\n new Error(`Codex plugin uninstall failed: ${reason}`),\n );\n return { success: false, reason };\n }\n return { success: true };\n }\n\n async installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n };\n\n // `codex plugin marketplace add` exits non-zero once the marketplace is\n // registered, so ask config.toml first. Without this the second run of\n // `mcp add` looked like a failure and reported nothing at all.\n if (await this.isPluginInstalled()) {\n return { success: true, alreadyInstalled: true };\n }\n\n const run = () =>\n spawnSync(binary, ['plugin', 'marketplace', 'add', 'PostHog/ai-plugin'], {\n encoding: 'utf-8',\n });\n\n let result = run();\n\n // Stale cache directory with no config.toml entry — clear it and retry\n if (\n result.status !== 0 &&\n STALE_MARKETPLACE_CACHE.test(result.stderr ?? '')\n ) {\n const staleDir = path.join(\n os.homedir(),\n '.codex',\n '.tmp',\n 'marketplaces',\n 'posthog',\n );\n try {\n fs.rmSync(staleDir, { recursive: true, force: true });\n } catch {\n // ignore — retry anyway\n }\n result = run();\n }\n\n if (result.status !== 0) {\n const stderr = result.stderr ?? '';\n // The marketplace was registered by something other than us (a manual\n // `codex plugin marketplace add`, or a version that writes config.toml\n // differently) — that's still \"already installed\", not a failure. The\n // stale-cache wording above is deliberately excluded: that one means the\n // plugin is NOT registered, and it only reaches here if the retry failed.\n if (\n ALREADY_INSTALLED_PATTERN.test(stderr) &&\n !STALE_MARKETPLACE_CACHE.test(stderr)\n ) {\n return { success: true, alreadyInstalled: true };\n }\n const reason = redactSecrets(stderr);\n analytics.captureException(\n new Error(`Codex plugin install failed: ${reason}`),\n );\n return { success: false, reason };\n }\n\n return { success: true };\n }\n}\n\nexport default CodexMCPClient;\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as fs from 'fs';\nimport { execSync } from 'node:child_process';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const OpenCodeMCPConfig = z\n .object({\n mcp: z.record(\n z.string(),\n z.object({\n type: z.literal('remote'),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ),\n })\n .passthrough();\n\nexport type OpenCodeMCPConfig = z.infer<typeof OpenCodeMCPConfig>;\n\nexport class OpenCodeMCPClient extends DefaultMCPClient {\n name = 'OpenCode';\n private opencodeBinaryPath: string | null = null;\n\n override getServerPropertyName(): string {\n return 'mcp';\n }\n\n private findOpenCodeBinary(): string | null {\n if (this.opencodeBinaryPath) return this.opencodeBinaryPath;\n try {\n const resolved = execSync('command -v opencode', { stdio: 'pipe' })\n .toString()\n .trim();\n if (resolved) {\n this.opencodeBinaryPath = resolved;\n return resolved;\n }\n } catch {\n // not in PATH\n }\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n return Promise.resolve(this.findOpenCodeBinary() !== null);\n }\n\n getConfigPath(): Promise<string> {\n const configDir = this.resolveConfigDir();\n const jsoncPath = path.join(configDir, 'opencode.jsonc');\n const jsonPath = path.join(configDir, 'opencode.json');\n if (fs.existsSync(jsoncPath)) return Promise.resolve(jsoncPath);\n return Promise.resolve(jsonPath);\n }\n\n private resolveConfigDir(): string {\n const envDir = runtimeEnv('OPENCODE_CONFIG_DIR');\n if (envDir) return envDir;\n\n const xdgHome = runtimeEnv('XDG_CONFIG_HOME');\n if (xdgHome) return path.join(xdgHome, 'opencode');\n\n return path.join(os.homedir(), '.config', 'opencode');\n }\n\n override getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n type: 'remote',\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import type { InstallResult } from './results';\n\nexport type PluginInstallResult = InstallResult;\n\nexport interface PluginCapable {\n supportsPlugin(): boolean;\n isPluginInstalled(): Promise<boolean>;\n installPlugin(): Promise<PluginInstallResult>;\n /** Uninstall the plugin. Absent when the client CLI has no uninstall surface. */\n removePlugin?(): Promise<PluginInstallResult>;\n /** True when the plugin ships its own posthog MCP server, making a direct entry redundant. */\n pluginBundlesMcpServer(): boolean;\n}\n\nexport function isPluginCapable<T>(client: T): client is T & PluginCapable {\n return (\n typeof client === 'object' &&\n client !== null &&\n 'supportsPlugin' in client &&\n 'installPlugin' in client\n );\n}\n","import type { Integration } from '@lib/constants';\nimport type { CloudRegion } from '@utils/types';\nimport { withProgress } from '../../telemetry';\nimport { analytics } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport { MCPClient } from './MCPClient';\nimport { CursorMCPClient } from './clients/cursor';\nimport { ClaudeCodeMCPClient } from './clients/claude-code';\nimport { ClaudeWebMCPClient } from './clients/claude-web';\nimport { VisualStudioCodeClient } from './clients/visual-studio-code';\nimport { ZedClient } from './clients/zed';\nimport { CodexMCPClient } from './clients/codex';\nimport { OpenCodeMCPClient } from './clients/opencode';\nimport { ALL_FEATURE_VALUES } from './defaults';\nimport { debug } from '@utils/debug';\nimport { isPluginCapable, PluginCapable } from './plugin-client';\nimport {\n McpClientStatus,\n namesWithStatus,\n toClientResult,\n type McpClientResult,\n} from './results';\n\nexport const getSupportedClients = async (): Promise<MCPClient[]> => {\n const allClients = [\n new ClaudeCodeMCPClient(),\n new ClaudeWebMCPClient(),\n new CodexMCPClient(),\n new CursorMCPClient(),\n new VisualStudioCodeClient(),\n new ZedClient(),\n new OpenCodeMCPClient(),\n ];\n const supportedClients: MCPClient[] = [];\n\n debug('Checking for supported MCP clients...');\n for (const client of allClients) {\n const isSupported = await client.isClientSupported();\n debug(`${client.name}: ${isSupported ? '✓ supported' : '✗ not supported'}`);\n if (isSupported) {\n supportedClients.push(client);\n }\n }\n debug(\n `Found ${supportedClients.length} supported client(s): ${supportedClients\n .map((c) => c.name)\n .join(', ')}`,\n );\n\n return supportedClients;\n};\n\n/** Per-client outcome, so a scripted caller can turn a failure into an exit code. */\nexport interface McpStepOutcome {\n /** Clients that ended up with the server, whether we wrote it or it was already there. */\n installed: string[];\n failed: string[];\n}\n\n/**\n * Add MCP server to clients. No prompts — pure orchestration.\n * Prompts are handled by McpScreen (TUI) or auto-accepted (CI).\n */\nexport const addMCPServerToClientsStep = async ({\n integration,\n local = false,\n ci = false,\n cloudRegion: _cloudRegion,\n features,\n apiKey,\n}: {\n integration?: Integration;\n local?: boolean;\n ci?: boolean;\n cloudRegion?: CloudRegion;\n features?: string[];\n apiKey?: string;\n}): Promise<McpStepOutcome> => {\n const ui = getUI();\n\n // CI mode: skip MCP installation entirely\n if (ci) {\n ui.log.info('Skipping MCP installation (CI mode)');\n return { installed: [], failed: [] };\n }\n\n const supportedClients = await getSupportedClients();\n\n if (supportedClients.length === 0) {\n ui.log.info(\n 'No supported MCP clients detected. Skipping MCP installation.',\n );\n return { installed: [], failed: [] };\n }\n\n // Auto-install to all supported clients\n const results = await withProgress('adding mcp servers', () =>\n addMCPServer(\n supportedClients,\n apiKey,\n features ?? [...ALL_FEATURE_VALUES],\n local,\n ),\n );\n\n const installed = namesWithStatus(results, McpClientStatus.Changed);\n const already = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // Report each outcome on its own — a blanket \"Added the MCP server to: ...\"\n // hid both the no-op re-runs and the outright failures.\n if (installed.length > 0) {\n ui.log.success(`Added the MCP server to:\\n${bulletList(installed)}`);\n }\n if (already.length > 0) {\n ui.log.info(\n `The PostHog MCP server was already installed, so nothing changed for:\\n${bulletList(\n already,\n )}`,\n );\n }\n if (failed.length > 0) {\n ui.log.warn(\n `Couldn't add the MCP server to:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n const withServer = [...installed, ...already];\n\n analytics.wizardCapture('mcp servers added', {\n // `clients` stays \"every client that ended up with the MCP server\", which is\n // what it meant before — the new properties break that down.\n clients: withServer,\n already_installed_clients: already,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: supportedClients.map((c) => c.name),\n integration,\n });\n\n return { installed: withServer, failed: failed.map((r) => r.name) };\n};\n\nconst bulletList = (items: string[]): string =>\n items.map((item) => ` - ${item}`).join('\\n');\n\nexport const removeMCPServerFromClientsStep = async ({\n integration,\n local = false,\n}: {\n integration?: Integration;\n local?: boolean;\n}): Promise<string[]> => {\n const ui = getUI();\n const installedClients = await getInstalledClients(local);\n if (installedClients.length === 0) {\n ui.log.info(\n 'The PostHog MCP server is not installed for any supported client. Nothing to remove.',\n );\n analytics.wizardCapture('mcp no servers to remove', {\n integration,\n });\n return [];\n }\n\n // Auto-remove from all installed clients\n const results = await withProgress('removing mcp servers', () =>\n removeMCPServer(installedClients, local),\n );\n\n const removed = namesWithStatus(results, McpClientStatus.Changed);\n const nothingToDo = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // This step used to print nothing at all, so a non-TTY `mcp remove` gave no\n // hint whether anything happened — let alone whether a client failed.\n if (removed.length > 0) {\n ui.log.success(`Removed the MCP server from:\\n${bulletList(removed)}`);\n }\n if (nothingToDo.length > 0) {\n ui.log.info(\n `No PostHog MCP entry left to remove for:\\n${bulletList(nothingToDo)}`,\n );\n }\n if (failed.length > 0) {\n ui.log.warn(\n `Couldn't remove the MCP server from:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n analytics.wizardCapture('mcp servers removed', {\n clients: removed,\n nothing_to_remove_clients: nothingToDo,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: installedClients.map((c) => c.name),\n integration,\n });\n\n return removed;\n};\n\nexport const getInstalledClients = async (\n local?: boolean,\n): Promise<MCPClient[]> => {\n const clients = await getSupportedClients();\n const installedClients: MCPClient[] = [];\n\n for (const client of clients) {\n // The plugin bundles its own posthog MCP server, so for removal purposes a\n // plugin install counts as installed even with no config entry (`--local`\n // targets only the local-dev entry and leaves the plugin alone).\n const pluginInstalled =\n !local && isPluginCapable(client) && (await client.isPluginInstalled());\n if ((await client.isServerInstalled(local)) || pluginInstalled) {\n installedClients.push(client);\n }\n }\n\n return installedClients;\n};\n\nexport const addMCPServer = async (\n clients: MCPClient[],\n personalApiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n const result = await client.addServer(\n personalApiKey,\n selectedFeatures,\n local,\n );\n results.push(toClientResult(client.name, result));\n } catch (err) {\n debug(`[addMCPServer] addServer threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n\nexport const getSupportedPluginClients = (\n clients: MCPClient[],\n): Array<MCPClient & PluginCapable> => {\n return clients.filter(isPluginCapable).filter((c) => c.supportsPlugin());\n};\n\nexport const installPlugins = async (\n clients: Array<MCPClient & PluginCapable>,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n results.push(toClientResult(client.name, await client.installPlugin()));\n } catch (err) {\n debug(`[installPlugins] installPlugin threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n\nexport const removeMCPServer = async (\n clients: MCPClient[],\n local?: boolean,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n let result = await client.removeServer(local);\n // The plugin bundles its own posthog server — leaving it installed makes\n // the removal a lie (`--local` never touches the plugin).\n if (!local && isPluginCapable(client) && client.removePlugin) {\n const plugin = await client.removePlugin();\n result =\n !result.success || !plugin.success\n ? {\n success: false,\n reason: [result.reason, plugin.reason]\n .filter(Boolean)\n .join('; '),\n }\n : {\n success: true,\n ...(result.alreadyInstalled && plugin.alreadyInstalled\n ? { alreadyInstalled: true }\n : {}),\n };\n }\n results.push(toClientResult(client.name, result));\n } catch (err) {\n debug(`[removeMCPServer] removeServer threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"add-mcp-server-to-clients-B6-ZL--P.js","names":["fs","path","path","os","path","os","fs","execSync","z","os","path","z","os","path","path","fs","z","path","fs","os"],"sources":["../src/steps/add-mcp-server-to-clients/MCPClient.ts","../src/steps/add-mcp-server-to-clients/clients/cursor.ts","../src/steps/add-mcp-server-to-clients/clients/claude-code.ts","../src/steps/add-mcp-server-to-clients/clients/claude-web.ts","../src/steps/add-mcp-server-to-clients/clients/visual-studio-code.ts","../src/steps/add-mcp-server-to-clients/clients/zed.ts","../src/steps/add-mcp-server-to-clients/clients/codex.ts","../src/steps/add-mcp-server-to-clients/clients/opencode.ts","../src/steps/add-mcp-server-to-clients/plugin-client.ts","../src/steps/add-mcp-server-to-clients/index.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as jsonc from 'jsonc-parser';\nimport { getDefaultServerConfig } from './defaults';\nimport type { InstallResult } from './results';\n\nexport type MCPServerConfig = Record<string, unknown>;\n\nexport abstract class MCPClient {\n name: string;\n abstract getConfigPath(): Promise<string>;\n abstract getServerPropertyName(): string;\n abstract isServerInstalled(local?: boolean): Promise<boolean>;\n abstract addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult>;\n abstract removeServer(local?: boolean): Promise<InstallResult>;\n abstract isClientSupported(): Promise<boolean>;\n}\n\nexport abstract class DefaultMCPClient extends MCPClient {\n name = 'Default';\n\n constructor() {\n super();\n }\n\n getServerPropertyName(): string {\n return 'mcpServers';\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getDefaultServerConfig(apiKey, selectedFeatures, local);\n }\n\n async isServerInstalled(local?: boolean): Promise<boolean> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return false;\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n const serverName = local ? 'posthog-local' : 'posthog';\n\n return (\n serverPropertyName in config && serverName in config[serverPropertyName]\n );\n } catch {\n return false;\n }\n }\n\n async addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n try {\n const configPath = await this.getConfigPath();\n const configDir = path.dirname(configPath);\n\n await fs.promises.mkdir(configDir, { recursive: true });\n\n const serverPropertyName = this.getServerPropertyName();\n let configContent = '';\n let existingConfig = {};\n\n if (fs.existsSync(configPath)) {\n configContent = await fs.promises.readFile(configPath, 'utf8');\n existingConfig = jsonc.parse(configContent) || {};\n }\n\n const newServerConfig = this.getServerConfig(\n apiKey,\n selectedFeatures,\n local,\n );\n const typedConfig = existingConfig as Record<string, any>;\n if (!typedConfig[serverPropertyName]) {\n typedConfig[serverPropertyName] = {};\n }\n const serverName = local ? 'posthog-local' : 'posthog';\n\n // An identical entry means this config is already set up — leave the file\n // untouched and report it, so a re-run says \"already installed\" instead of\n // claiming a write that changed nothing. A differing entry (new features,\n // new key) still gets overwritten and reported as installed.\n const existingServerConfig = typedConfig[serverPropertyName][serverName];\n if (\n existingServerConfig !== undefined &&\n JSON.stringify(existingServerConfig) === JSON.stringify(newServerConfig)\n ) {\n return { success: true, alreadyInstalled: true };\n }\n\n typedConfig[serverPropertyName][serverName] = newServerConfig;\n\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n newServerConfig,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async removeServer(local?: boolean): Promise<InstallResult> {\n let configPath = '';\n try {\n configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return { success: true, alreadyInstalled: true };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n\n const serverName = local ? 'posthog-local' : 'posthog';\n\n if (\n serverPropertyName in config &&\n serverName in config[serverPropertyName]\n ) {\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n undefined,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n }\n // No PostHog entry to delete — the config changed under us between the\n // detection pass and now. Nothing failed, so don't report a failure.\n return { success: true, alreadyInstalled: true };\n } catch (error) {\n return {\n success: false,\n reason: `${configPath}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n };\n }\n }\n}\n","import {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClientConfig,\n getNativeHTTPServerConfig,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport { z } from 'zod';\n\nexport const CursorMCPConfig = DefaultMCPClientConfig;\n\nexport type CursorMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CursorMCPClient extends DefaultMCPClient {\n name = 'Cursor';\n\n constructor() {\n super();\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'win32',\n );\n }\n\n async getConfigPath(): Promise<string> {\n return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getNativeHTTPServerConfig(apiKey, selectedFeatures, local);\n }\n}\n","import { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport {\n DefaultMCPClientConfig,\n buildMCPUrl,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\nimport {\n redactSecrets,\n type InstallResult,\n} from '@steps/add-mcp-server-to-clients/results';\nimport { LoginCapable } from '@steps/add-mcp-server-to-clients/login-client';\nimport { z } from 'zod';\nimport { execSync } from 'child_process';\nimport { analytics } from '@utils/analytics';\nimport { debug } from '@utils/debug';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport const ClaudeCodeMCPConfig = DefaultMCPClientConfig;\n\nexport type ClaudeCodeMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class ClaudeCodeMCPClient\n extends DefaultMCPClient\n implements PluginCapable, LoginCapable\n{\n name = 'Claude Code';\n private claudeBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findClaudeBinary(): string | null {\n if (this.claudeBinaryPath) {\n return this.claudeBinaryPath;\n }\n\n // Common installation paths for Claude Code CLI\n const possiblePaths = [\n path.join(os.homedir(), '.claude', 'local', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\n for (const claudePath of possiblePaths) {\n if (fs.existsSync(claudePath)) {\n debug(` Found claude binary at: ${claudePath}`);\n this.claudeBinaryPath = claudePath;\n return claudePath;\n }\n }\n\n // Try PATH as fallback\n try {\n execSync('command -v claude', { stdio: 'pipe' });\n debug(' Found claude in PATH');\n this.claudeBinaryPath = 'claude';\n return 'claude';\n } catch {\n // Not in PATH\n }\n\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n try {\n debug(' Checking for Claude Code...');\n const claudeBinary = this.findClaudeBinary();\n\n if (!claudeBinary) {\n debug(' Claude Code not found. Installation paths checked:');\n debug(` - ${path.join(os.homedir(), '.claude', 'local', 'claude')}`);\n debug(` - /usr/local/bin/claude`);\n debug(` - /opt/homebrew/bin/claude`);\n debug(` - PATH`);\n return Promise.resolve(false);\n }\n\n const output = execSync(`${claudeBinary} --version`, { stdio: 'pipe' });\n const version = output.toString().trim();\n debug(` Claude Code detected: ${version}`);\n return Promise.resolve(true);\n } catch (error) {\n debug(\n ` Claude Code check failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return Promise.resolve(false);\n }\n }\n\n isServerInstalled(local?: boolean): Promise<boolean> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve(false);\n const serverName = local ? 'posthog-local' : 'posthog';\n // `mcp get <name>` exits non-zero when the entry doesn't exist. A substring\n // scan of `mcp list` also matches the claude.ai \"PostHog\" connector and the\n // plugin's `plugin:posthog:posthog`, reporting installed forever.\n try {\n execSync(`${binary} mcp get ${serverName}`, { stdio: 'pipe' });\n return Promise.resolve(true);\n } catch {\n return Promise.resolve(false);\n }\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n });\n\n const serverName = local ? 'posthog-local' : 'posthog';\n const url = buildMCPUrl(selectedFeatures, local);\n const args = [\n 'mcp',\n 'add',\n '--transport',\n 'http',\n '--scope',\n 'user',\n serverName,\n url,\n ];\n if (apiKey) {\n args.push('--header', `Authorization: Bearer ${apiKey}`);\n }\n\n try {\n execSync(`${binary} ${args.map((a) => JSON.stringify(a)).join(' ')}`, {\n stdio: 'pipe',\n });\n return Promise.resolve({ success: true });\n } catch (error) {\n // The failing command echoes back the Authorization header we passed, so\n // redact before this reaches a log, the screen, or an exception report.\n const msg = redactSecrets(\n error instanceof Error ? error.message : String(error),\n );\n if (msg.includes('already exists')) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n analytics.captureException(\n new Error(`Claude Code MCP add failed: ${msg}`),\n );\n return Promise.resolve({ success: false, reason: msg });\n }\n }\n\n /** Claude Code's own login runs its OAuth and owns the token; the wizard only surfaces the command. */\n loginCommand(local?: boolean): string {\n return `claude mcp login ${local ? 'posthog-local' : 'posthog'}`;\n }\n\n /** The plugin bundles its own `posthog` server, addressed as `plugin:<plugin>:<server>`. */\n pluginLoginCommand(): string {\n return 'claude mcp login plugin:posthog:posthog';\n }\n\n async removePlugin(): Promise<PluginInstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n };\n\n if (!(await this.isPluginInstalled())) {\n return { success: true, alreadyInstalled: true };\n }\n\n try {\n execSync(`${binary} plugin uninstall posthog`, { stdio: 'pipe' });\n return { success: true };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n analytics.captureException(\n new Error(`Claude Code plugin uninstall failed: ${msg}`),\n );\n return { success: false, reason: msg };\n }\n }\n\n removeServer(local?: boolean): Promise<InstallResult> {\n const claudeBinary = this.findClaudeBinary();\n if (!claudeBinary) {\n return Promise.resolve({\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n });\n }\n\n const serverName = local ? 'posthog-local' : 'posthog';\n const command = `${claudeBinary} mcp remove --scope user ${serverName}`;\n\n try {\n execSync(command, { stdio: 'pipe' });\n } catch (error) {\n const reason = redactSecrets(\n error instanceof Error ? error.message : String(error),\n );\n // Removing something that isn't there is the requested end state, not a\n // failure to report.\n if (/no( such)? mcp server|not found/i.test(reason)) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n analytics.captureException(\n new Error(`Failed to remove server from Claude Code: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n\n return Promise.resolve({ success: true });\n }\n\n /** The plugin ships mcp.json with the posthog server — no direct entry needed. */\n pluginBundlesMcpServer(): boolean {\n return true;\n }\n\n supportsPlugin(): boolean {\n return this.findClaudeBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve(false);\n try {\n const output = execSync(`${binary} plugin list`, {\n stdio: 'pipe',\n }).toString();\n return Promise.resolve(output.toLowerCase().includes('posthog'));\n } catch {\n return Promise.resolve(false);\n }\n }\n\n async installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The claude CLI is no longer on your PATH.',\n };\n\n // Ask before installing so a re-run reports \"already installed\" rather than\n // relying on the CLI's error text to spot the no-op.\n if (await this.isPluginInstalled()) {\n return { success: true, alreadyInstalled: true };\n }\n\n try {\n execSync(`${binary} plugin install posthog`, { stdio: 'pipe' });\n return { success: true };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('already installed') || msg.includes('already exists')) {\n return { success: true, alreadyInstalled: true };\n }\n analytics.captureException(\n new Error(`Claude Code plugin install failed: ${msg}`),\n );\n return { success: false, reason: msg };\n }\n }\n}\n","import { MCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport type { InstallResult } from '@steps/add-mcp-server-to-clients/results';\nimport { BrowserFinishable } from '@steps/add-mcp-server-to-clients/browser-client';\nimport { openTrackedLink } from '@utils/links';\n\n/**\n * Claude Desktop / Claude.ai (web). PostHog ships here as a hosted connector,\n * not a local config — so instead of writing files we open the connector\n * directory page and let the user sign in and click \"Connect\".\n */\nexport class ClaudeWebMCPClient extends MCPClient implements BrowserFinishable {\n name = 'Claude Desktop/Web';\n connectorUrl = 'https://claude.ai/directory/connectors/posthog';\n finishInstruction = 'Sign in and click \"Connect\" to finish.';\n\n isClientSupported(): Promise<boolean> {\n // Browser-based — available on every platform.\n return Promise.resolve(true);\n }\n\n isServerInstalled(): Promise<boolean> {\n // The connector lives in the user's Claude account; nothing local to\n // inspect. Returning false also keeps it out of `mcp remove`.\n return Promise.resolve(false);\n }\n\n addServer(): Promise<InstallResult> {\n // Not a PostHog property, so no UTMs — just the tracked open.\n openTrackedLink(this.connectorUrl, 'claude-web-connector', {\n auto: true,\n skipUtm: true,\n });\n return Promise.resolve({ success: true });\n }\n\n removeServer(): Promise<InstallResult> {\n // The connector lives in the user's Claude account, so `mcp remove` can't\n // touch it. It never reaches here today (isServerInstalled is always\n // false), but say where to go if it ever does.\n return Promise.resolve({\n success: false,\n reason:\n 'This connector is managed in your Claude account — remove it at claude.ai/settings/connectors.',\n });\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n getServerPropertyName(): string {\n throw new Error('Not implemented');\n }\n}\n\nexport default ClaudeWebMCPClient;\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const VisualStudioCodeMCPConfig = z\n .object({\n servers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n type: z.enum(['http', 'sse']),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type VisualStudioCodeMCPConfig = z.infer<\n typeof VisualStudioCodeMCPConfig\n>;\n\nexport class VisualStudioCodeClient extends DefaultMCPClient {\n name = 'Visual Studio Code';\n\n getServerPropertyName(): string {\n return 'servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' ||\n process.platform === 'win32' ||\n process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isWindows = process.platform === 'win32';\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(\n homeDir,\n 'Library',\n 'Application Support',\n 'Code',\n 'User',\n 'mcp.json',\n ),\n );\n }\n\n if (isWindows) {\n return Promise.resolve(\n path.join(runtimeEnv('APPDATA') || '', 'Code', 'User', 'mcp.json'),\n );\n }\n\n if (isLinux) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'Code', 'User', 'mcp.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n type: 'http',\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const ZedMCPConfig = z\n .object({\n context_servers: z.record(\n z.string(),\n z.union([\n z.object({\n enabled: z.boolean().optional(),\n source: z.string().optional(),\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n enabled: z.boolean().optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type ZedMCPConfig = z.infer<typeof ZedMCPConfig>;\n\nexport class ZedClient extends DefaultMCPClient {\n name = 'Zed';\n\n getServerPropertyName(): string {\n return 'context_servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n if (isLinux) {\n // https://zed.dev/docs/configuring-zed#settings-files\n const xdgConfigHome = runtimeEnv('XDG_CONFIG_HOME');\n if (xdgConfigHome) {\n return Promise.resolve(\n path.join(xdgConfigHome, 'zed', 'settings.json'),\n );\n }\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n enabled: true,\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import { z } from 'zod';\nimport { execSync, spawnSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nimport { LoginCapable } from '@steps/add-mcp-server-to-clients/login-client';\nimport { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport {\n DefaultMCPClientConfig,\n buildMCPUrl,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\nimport {\n redactSecrets,\n type InstallResult,\n} from '@steps/add-mcp-server-to-clients/results';\n\nimport { analytics } from '@utils/analytics';\n\n/** Wording codex uses when the thing we're adding is already registered. */\nconst ALREADY_INSTALLED_PATTERN =\n /already (installed|exists|added|registered)/i;\n/** Wording that means the opposite: a cache entry exists but the plugin doesn't. */\nconst STALE_MARKETPLACE_CACHE = /already added from a different source/i;\n\n/**\n * Codex allows servers 10s to finish the MCP initialize handshake, and a remote\n * OAuth handshake can exceed that on a cold start — the \"servers were not\n * initialized\" warning.\n */\nconst STARTUP_TIMEOUT_SEC = 30;\n\n/**\n * The server's table header. TOML accepts a bare or quoted key for the same\n * table, and matching only the bare form means we append a second definition of\n * a table that already exists — a duplicate-key error that takes the user's\n * whole config down, not just PostHog's entry.\n */\nconst sectionHeader = (serverName: string): RegExp =>\n new RegExp(\n `^\\\\[mcp_servers\\\\.(?:${serverName}|\"${serverName}\")\\\\][ \\\\t]*$`,\n 'm',\n );\n\n/**\n * Set `key = value` inside a section body, inserting it when absent. Scans the\n * whole body rather than the line after the header: TOML does not care about\n * key order, and assuming it does means silently matching nothing.\n */\nconst setKey = (body: string, key: string, value: string): string => {\n const existing = new RegExp(`^[ \\\\t]*${key}[ \\\\t]*=.*$`, 'm');\n return existing.test(body)\n ? body.replace(existing, `${key} = ${value}`)\n : `\\n${key} = ${value}${body}`;\n};\n\nexport const CodexMCPConfig = DefaultMCPClientConfig;\n\nexport type CodexMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CodexMCPClient\n extends DefaultMCPClient\n implements PluginCapable, LoginCapable\n{\n name = 'Codex';\n private codexBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findCodexBinary(): string | null {\n if (this.codexBinaryPath) return this.codexBinaryPath;\n try {\n const resolved = execSync('command -v codex', { stdio: 'pipe' })\n .toString()\n .trim();\n if (resolved) {\n this.codexBinaryPath = resolved;\n return resolved;\n }\n } catch {\n // not in PATH\n }\n return null;\n }\n\n private configPath(): string {\n return path.join(os.homedir(), '.codex', 'config.toml');\n }\n\n isClientSupported(): Promise<boolean> {\n return Promise.resolve(this.findCodexBinary() !== null);\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n isServerInstalled(local?: boolean): Promise<boolean> {\n const serverName = local ? 'posthog-local' : 'posthog';\n // The `[mcp_servers.<name>]` section in config.toml — both the CLI and the\n // desktop app read (and `codex mcp add` writes) this file, and a substring\n // scan of `mcp list` matches unrelated posthog-ish servers.\n try {\n const contents = fs.readFileSync(this.configPath(), 'utf-8');\n return Promise.resolve(sectionHeader(serverName).test(contents));\n } catch {\n return Promise.resolve(false);\n }\n }\n\n addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<InstallResult> {\n const serverName = local ? 'posthog-local' : 'posthog';\n const url = buildMCPUrl(selectedFeatures, local);\n\n // Api-key installs go through the CLI for its bearer-token env wiring.\n if (apiKey) {\n const binary = this.findCodexBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'An API-key install into Codex needs the codex CLI.',\n });\n const args = [\n 'mcp',\n 'add',\n serverName,\n '--url',\n url,\n '--bearer-token-env-var',\n 'POSTHOG_AUTH_HEADER',\n ];\n const env = { ...process.env, POSTHOG_AUTH_HEADER: `Bearer ${apiKey}` };\n const result = spawnSync(binary, args, { encoding: 'utf-8', env });\n if (result.status !== 0) {\n const stderr = result.stderr ?? '';\n if (ALREADY_INSTALLED_PATTERN.test(stderr)) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n const reason = redactSecrets(stderr);\n analytics.captureException(\n new Error(`Codex MCP add failed: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n return Promise.resolve({ success: true });\n }\n\n // OAuth installs write config.toml directly: running `codex mcp add` here\n // would hang the wizard on its built-in OAuth browser wait. Codex nags\n // about the unauthenticated server until the surfaced `codex mcp login`\n // runs — the same interim state as Claude Code's \"needs authentication\".\n return Promise.resolve(this.writeServerSection(serverName, url));\n }\n\n /**\n * Create or update the `[mcp_servers.<name>]` section in config.toml, editing\n * in place so the user's other servers, key order, and comments survive.\n */\n private writeServerSection(serverName: string, url: string): InstallResult {\n const configPath = this.configPath();\n try {\n // A machine that has codex installed but has never run it has no\n // ~/.codex at all — `codex mcp add` used to create it for us.\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n const contents = fs.existsSync(configPath)\n ? fs.readFileSync(configPath, 'utf-8')\n : '';\n\n const header = sectionHeader(serverName).exec(contents);\n if (!header) {\n const gap = contents === '' || contents.endsWith('\\n\\n') ? '' : '\\n';\n const pad = contents === '' || contents.endsWith('\\n') ? '' : '\\n';\n this.write(\n configPath,\n `${contents}${pad}${gap}[mcp_servers.${serverName}]\\n` +\n `url = \"${url}\"\\nstartup_timeout_sec = ${STARTUP_TIMEOUT_SEC}\\n`,\n );\n return { success: true };\n }\n\n // Everything up to the next table header belongs to this server.\n const start = header.index + header[0].length;\n const rest = contents.slice(start);\n const next = /^\\[/m.exec(rest);\n const end = next ? start + next.index : contents.length;\n\n const body = contents.slice(start, end);\n const updated = setKey(\n setKey(body, 'url', `\"${url}\"`),\n 'startup_timeout_sec',\n String(STARTUP_TIMEOUT_SEC),\n );\n if (updated === body) return { success: true, alreadyInstalled: true };\n\n this.write(\n configPath,\n contents.slice(0, start) + updated + contents.slice(end),\n );\n return { success: true };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n analytics.captureException(\n new Error(`Codex config.toml write failed: ${reason}`),\n );\n return { success: false, reason };\n }\n }\n\n /** Write via a sibling temp file: a crash mid-write must not truncate the config. */\n private write(configPath: string, contents: string): void {\n const tmp = `${configPath}.wizard-tmp`;\n fs.writeFileSync(tmp, contents);\n fs.renameSync(tmp, configPath);\n }\n\n /** Codex's own login runs its OAuth and owns the token; the wizard only surfaces the command. */\n loginCommand(local?: boolean): string | null {\n if (!this.findCodexBinary()) return null;\n return `codex mcp login ${local ? 'posthog-local' : 'posthog'}`;\n }\n\n removeServer(local?: boolean): Promise<InstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return Promise.resolve({\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n });\n\n // `local` was ignored here, so `mcp remove --local` reported success while\n // leaving the posthog-local server in place.\n const serverName = local ? 'posthog-local' : 'posthog';\n const result = spawnSync(binary, ['mcp', 'remove', serverName], {\n encoding: 'utf-8',\n });\n\n if (result.error || result.status !== 0) {\n const reason = redactSecrets(\n result.error?.message ?? result.stderr ?? 'codex mcp remove failed',\n );\n analytics.captureException(\n new Error(`Failed to remove server from Codex CLI: ${reason}`),\n );\n return Promise.resolve({ success: false, reason });\n }\n\n return Promise.resolve({ success: true });\n }\n\n /** The codex marketplace plugin ships skills only — the MCP server needs its own entry. */\n pluginBundlesMcpServer(): boolean {\n return false;\n }\n\n supportsPlugin(): boolean {\n return this.findCodexBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const configPath = path.join(os.homedir(), '.codex', 'config.toml');\n try {\n const contents = fs.readFileSync(configPath, 'utf-8');\n // Marketplace installs appear as [marketplaces.posthog] in config.toml\n return Promise.resolve(\n contents.toLowerCase().includes('[marketplaces.posthog]'),\n );\n } catch {\n return Promise.resolve(false);\n }\n }\n\n async removePlugin(): Promise<PluginInstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n };\n\n if (!(await this.isPluginInstalled())) {\n return { success: true, alreadyInstalled: true };\n }\n\n const result = spawnSync(\n binary,\n ['plugin', 'marketplace', 'remove', 'posthog'],\n { encoding: 'utf-8' },\n );\n if (result.status !== 0) {\n const reason = redactSecrets(\n result.stderr ?? 'codex plugin marketplace remove failed',\n );\n analytics.captureException(\n new Error(`Codex plugin uninstall failed: ${reason}`),\n );\n return { success: false, reason };\n }\n return { success: true };\n }\n\n async installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findCodexBinary();\n if (!binary)\n return {\n success: false,\n reason: 'The codex CLI is no longer on your PATH.',\n };\n\n // `codex plugin marketplace add` exits non-zero once the marketplace is\n // registered, so ask config.toml first. Without this the second run of\n // `mcp add` looked like a failure and reported nothing at all.\n if (await this.isPluginInstalled()) {\n return { success: true, alreadyInstalled: true };\n }\n\n const run = () =>\n spawnSync(binary, ['plugin', 'marketplace', 'add', 'PostHog/ai-plugin'], {\n encoding: 'utf-8',\n });\n\n let result = run();\n\n // Stale cache directory with no config.toml entry — clear it and retry\n if (\n result.status !== 0 &&\n STALE_MARKETPLACE_CACHE.test(result.stderr ?? '')\n ) {\n const staleDir = path.join(\n os.homedir(),\n '.codex',\n '.tmp',\n 'marketplaces',\n 'posthog',\n );\n try {\n fs.rmSync(staleDir, { recursive: true, force: true });\n } catch {\n // ignore — retry anyway\n }\n result = run();\n }\n\n if (result.status !== 0) {\n const stderr = result.stderr ?? '';\n // The marketplace was registered by something other than us (a manual\n // `codex plugin marketplace add`, or a version that writes config.toml\n // differently) — that's still \"already installed\", not a failure. The\n // stale-cache wording above is deliberately excluded: that one means the\n // plugin is NOT registered, and it only reaches here if the retry failed.\n if (\n ALREADY_INSTALLED_PATTERN.test(stderr) &&\n !STALE_MARKETPLACE_CACHE.test(stderr)\n ) {\n return { success: true, alreadyInstalled: true };\n }\n const reason = redactSecrets(stderr);\n analytics.captureException(\n new Error(`Codex plugin install failed: ${reason}`),\n );\n return { success: false, reason };\n }\n\n return { success: true };\n }\n}\n\nexport default CodexMCPClient;\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as fs from 'fs';\nimport { execSync } from 'node:child_process';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const OpenCodeMCPConfig = z\n .object({\n mcp: z.record(\n z.string(),\n z.object({\n type: z.literal('remote'),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ),\n })\n .passthrough();\n\nexport type OpenCodeMCPConfig = z.infer<typeof OpenCodeMCPConfig>;\n\nexport class OpenCodeMCPClient extends DefaultMCPClient {\n name = 'OpenCode';\n private opencodeBinaryPath: string | null = null;\n\n override getServerPropertyName(): string {\n return 'mcp';\n }\n\n private findOpenCodeBinary(): string | null {\n if (this.opencodeBinaryPath) return this.opencodeBinaryPath;\n try {\n const resolved = execSync('command -v opencode', { stdio: 'pipe' })\n .toString()\n .trim();\n if (resolved) {\n this.opencodeBinaryPath = resolved;\n return resolved;\n }\n } catch {\n // not in PATH\n }\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n return Promise.resolve(this.findOpenCodeBinary() !== null);\n }\n\n getConfigPath(): Promise<string> {\n const configDir = this.resolveConfigDir();\n const jsoncPath = path.join(configDir, 'opencode.jsonc');\n const jsonPath = path.join(configDir, 'opencode.json');\n if (fs.existsSync(jsoncPath)) return Promise.resolve(jsoncPath);\n return Promise.resolve(jsonPath);\n }\n\n private resolveConfigDir(): string {\n const envDir = runtimeEnv('OPENCODE_CONFIG_DIR');\n if (envDir) return envDir;\n\n const xdgHome = runtimeEnv('XDG_CONFIG_HOME');\n if (xdgHome) return path.join(xdgHome, 'opencode');\n\n return path.join(os.homedir(), '.config', 'opencode');\n }\n\n override getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n type: 'remote',\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import type { InstallResult } from './results';\n\nexport type PluginInstallResult = InstallResult;\n\nexport interface PluginCapable {\n supportsPlugin(): boolean;\n isPluginInstalled(): Promise<boolean>;\n installPlugin(): Promise<PluginInstallResult>;\n /** Uninstall the plugin. Absent when the client CLI has no uninstall surface. */\n removePlugin?(): Promise<PluginInstallResult>;\n /** True when the plugin ships its own posthog MCP server, making a direct entry redundant. */\n pluginBundlesMcpServer(): boolean;\n}\n\nexport function isPluginCapable<T>(client: T): client is T & PluginCapable {\n return (\n typeof client === 'object' &&\n client !== null &&\n 'supportsPlugin' in client &&\n 'installPlugin' in client\n );\n}\n","import type { Integration } from '@lib/constants';\nimport type { CloudRegion } from '@utils/types';\nimport { withProgress } from '../../telemetry';\nimport { analytics } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport { MCPClient } from './MCPClient';\nimport { CursorMCPClient } from './clients/cursor';\nimport { ClaudeCodeMCPClient } from './clients/claude-code';\nimport { ClaudeWebMCPClient } from './clients/claude-web';\nimport { VisualStudioCodeClient } from './clients/visual-studio-code';\nimport { ZedClient } from './clients/zed';\nimport { CodexMCPClient } from './clients/codex';\nimport { OpenCodeMCPClient } from './clients/opencode';\nimport { ALL_FEATURE_VALUES } from './defaults';\nimport { debug } from '@utils/debug';\nimport { isPluginCapable, PluginCapable } from './plugin-client';\nimport {\n McpClientStatus,\n namesWithStatus,\n toClientResult,\n type McpClientResult,\n} from './results';\n\nexport const getSupportedClients = async (): Promise<MCPClient[]> => {\n const allClients = [\n new ClaudeCodeMCPClient(),\n new ClaudeWebMCPClient(),\n new CodexMCPClient(),\n new CursorMCPClient(),\n new VisualStudioCodeClient(),\n new ZedClient(),\n new OpenCodeMCPClient(),\n ];\n const supportedClients: MCPClient[] = [];\n\n debug('Checking for supported MCP clients...');\n for (const client of allClients) {\n const isSupported = await client.isClientSupported();\n debug(`${client.name}: ${isSupported ? '✓ supported' : '✗ not supported'}`);\n if (isSupported) {\n supportedClients.push(client);\n }\n }\n debug(\n `Found ${supportedClients.length} supported client(s): ${supportedClients\n .map((c) => c.name)\n .join(', ')}`,\n );\n\n return supportedClients;\n};\n\n/** Per-client outcome, so a scripted caller can turn a failure into an exit code. */\nexport interface McpStepOutcome {\n /** Clients that ended up with the server, whether we wrote it or it was already there. */\n installed: string[];\n failed: string[];\n}\n\n/**\n * Add MCP server to clients. No prompts — pure orchestration.\n * Prompts are handled by McpScreen (TUI) or auto-accepted (CI).\n */\nexport const addMCPServerToClientsStep = async ({\n integration,\n local = false,\n ci = false,\n cloudRegion: _cloudRegion,\n features,\n apiKey,\n}: {\n integration?: Integration;\n local?: boolean;\n ci?: boolean;\n cloudRegion?: CloudRegion;\n features?: string[];\n apiKey?: string;\n}): Promise<McpStepOutcome> => {\n const ui = getUI();\n\n // CI mode: skip MCP installation entirely\n if (ci) {\n ui.log.info('Skipping MCP installation (CI mode)');\n return { installed: [], failed: [] };\n }\n\n const supportedClients = await getSupportedClients();\n\n if (supportedClients.length === 0) {\n ui.log.info(\n 'No supported MCP clients detected. Skipping MCP installation.',\n );\n return { installed: [], failed: [] };\n }\n\n // Auto-install to all supported clients\n const results = await withProgress('adding mcp servers', () =>\n addMCPServer(\n supportedClients,\n apiKey,\n features ?? [...ALL_FEATURE_VALUES],\n local,\n ),\n );\n\n const installed = namesWithStatus(results, McpClientStatus.Changed);\n const already = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // Report each outcome on its own — a blanket \"Added the MCP server to: ...\"\n // hid both the no-op re-runs and the outright failures.\n if (installed.length > 0) {\n ui.log.success(`Added the MCP server to:\\n${bulletList(installed)}`);\n }\n if (already.length > 0) {\n ui.log.info(\n `The PostHog MCP server was already installed, so nothing changed for:\\n${bulletList(\n already,\n )}`,\n );\n }\n if (failed.length > 0) {\n ui.log.warn(\n `Couldn't add the MCP server to:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n const withServer = [...installed, ...already];\n\n analytics.wizardCapture('mcp servers added', {\n // `clients` stays \"every client that ended up with the MCP server\", which is\n // what it meant before — the new properties break that down.\n clients: withServer,\n already_installed_clients: already,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: supportedClients.map((c) => c.name),\n integration,\n });\n\n return { installed: withServer, failed: failed.map((r) => r.name) };\n};\n\nconst bulletList = (items: string[]): string =>\n items.map((item) => ` - ${item}`).join('\\n');\n\nexport const removeMCPServerFromClientsStep = async ({\n integration,\n local = false,\n}: {\n integration?: Integration;\n local?: boolean;\n}): Promise<string[]> => {\n const ui = getUI();\n const installedClients = await getInstalledClients(local);\n if (installedClients.length === 0) {\n ui.log.info(\n 'The PostHog MCP server is not installed for any supported client. Nothing to remove.',\n );\n analytics.wizardCapture('mcp no servers to remove', {\n integration,\n });\n return [];\n }\n\n // Auto-remove from all installed clients\n const results = await withProgress('removing mcp servers', () =>\n removeMCPServer(installedClients, local),\n );\n\n const removed = namesWithStatus(results, McpClientStatus.Changed);\n const nothingToDo = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // This step used to print nothing at all, so a non-TTY `mcp remove` gave no\n // hint whether anything happened — let alone whether a client failed.\n if (removed.length > 0) {\n ui.log.success(`Removed the MCP server from:\\n${bulletList(removed)}`);\n }\n if (nothingToDo.length > 0) {\n ui.log.info(\n `No PostHog MCP entry left to remove for:\\n${bulletList(nothingToDo)}`,\n );\n }\n if (failed.length > 0) {\n ui.log.warn(\n `Couldn't remove the MCP server from:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n analytics.wizardCapture('mcp servers removed', {\n clients: removed,\n nothing_to_remove_clients: nothingToDo,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: installedClients.map((c) => c.name),\n integration,\n });\n\n return removed;\n};\n\nexport const getInstalledClients = async (\n local?: boolean,\n): Promise<MCPClient[]> => {\n const clients = await getSupportedClients();\n const installedClients: MCPClient[] = [];\n\n for (const client of clients) {\n // The plugin bundles its own posthog MCP server, so for removal purposes a\n // plugin install counts as installed even with no config entry (`--local`\n // targets only the local-dev entry and leaves the plugin alone).\n const pluginInstalled =\n !local && isPluginCapable(client) && (await client.isPluginInstalled());\n if ((await client.isServerInstalled(local)) || pluginInstalled) {\n installedClients.push(client);\n }\n }\n\n return installedClients;\n};\n\nexport const addMCPServer = async (\n clients: MCPClient[],\n personalApiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n const result = await client.addServer(\n personalApiKey,\n selectedFeatures,\n local,\n );\n results.push(toClientResult(client.name, result));\n } catch (err) {\n debug(`[addMCPServer] addServer threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n\nexport const getSupportedPluginClients = (\n clients: MCPClient[],\n): Array<MCPClient & PluginCapable> => {\n return clients.filter(isPluginCapable).filter((c) => c.supportsPlugin());\n};\n\nexport const installPlugins = async (\n clients: Array<MCPClient & PluginCapable>,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n results.push(toClientResult(client.name, await client.installPlugin()));\n } catch (err) {\n debug(`[installPlugins] installPlugin threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n\nexport const removeMCPServer = async (\n clients: MCPClient[],\n local?: boolean,\n): Promise<McpClientResult[]> => {\n const results: McpClientResult[] = [];\n for (const client of clients) {\n try {\n let result = await client.removeServer(local);\n // The plugin bundles its own posthog server — leaving it installed makes\n // the removal a lie (`--local` never touches the plugin).\n if (!local && isPluginCapable(client) && client.removePlugin) {\n const plugin = await client.removePlugin();\n result =\n !result.success || !plugin.success\n ? {\n success: false,\n reason: [result.reason, plugin.reason]\n .filter(Boolean)\n .join('; '),\n }\n : {\n success: true,\n ...(result.alreadyInstalled && plugin.alreadyInstalled\n ? { alreadyInstalled: true }\n : {}),\n };\n }\n results.push(toClientResult(client.name, result));\n } catch (err) {\n debug(`[removeMCPServer] removeServer threw for ${client.name}: ${err}`);\n results.push(\n toClientResult(client.name, {\n success: false,\n reason: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n }\n return results;\n};\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { n as __require } from "./rolldown-runtime-B_-DWIq7.js";
2
- import { a as AgentSignals, o as REMARK_INSTRUCTION, s as classifyAuthFailure } from "./errors-BSdz2lsl.js";
3
- import { G as POSTHOG_FLAG_HEADER_PREFIX, J as POSTHOG_PROPERTY_HEADER_PREFIX, a as getLogFilePath, dt as WIZARD_REMARK_EVENT_NAME, f as getUI, ht as wizardUserAgentForProgram, o as initLogFile, r as debug, s as logToFile, xt as runtimeEnv } from "./debug-BM0fZaGl.js";
4
- import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-Bki7dQhv.js";
5
- import { n as analytics } from "./analytics-DTyJClPr.js";
6
- import { a as safeReadFile, i as readProjectFile, o as walkProjectFiles } from "./bounded-fs-BWX25ixc.js";
7
- import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-CooWEh9N.js";
8
- import { _ as modelCapabilities, m as writeJsonAtomic, o as buildOrchestratorTools, p as makeMutex, y as triageModelFor } from "./queue-tools-KosDptd6.js";
9
- import { b as coerceAuditChecks, g as AUDIT_CHECKS_FILE, l as prewarmYaraScanner, n as createPostToolUseYaraHooks, p as scanInstalledSkill, r as createPreToolUseYaraHooks } from "./yara-hooks-BpngckdZ.js";
2
+ import { a as AgentSignals, o as REMARK_INSTRUCTION, s as classifyAuthFailure } from "./errors-u8z27V-x.js";
3
+ import { G as POSTHOG_FLAG_HEADER_PREFIX, J as POSTHOG_PROPERTY_HEADER_PREFIX, a as getLogFilePath, dt as WIZARD_REMARK_EVENT_NAME, f as getUI, ht as wizardUserAgentForProgram, o as initLogFile, r as debug, s as logToFile, xt as runtimeEnv } from "./debug-YQdeZulR.js";
4
+ import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-CwQPZN4y.js";
5
+ import { n as analytics } from "./analytics-D54mLptm.js";
6
+ import { a as safeReadFile, i as readProjectFile, o as walkProjectFiles } from "./bounded-fs-DHIaH3Sc.js";
7
+ import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-D54j2gmb.js";
8
+ import { _ as modelCapabilities, m as writeJsonAtomic, o as buildOrchestratorTools, p as makeMutex, y as triageModelFor } from "./queue-tools-DGaHf3n-.js";
9
+ import { b as coerceAuditChecks, g as AUDIT_CHECKS_FILE, l as prewarmYaraScanner, n as createPostToolUseYaraHooks, p as scanInstalledSkill, r as createPreToolUseYaraHooks } from "./yara-hooks-CL2LVEgO.js";
10
10
  import { createRequire } from "node:module";
11
11
  import * as fs$1 from "fs";
12
12
  import fs from "fs";
@@ -19,6 +19,34 @@ import { z } from "zod";
19
19
  import * as os from "os";
20
20
  import { unzipSync } from "fflate";
21
21
  import { randomUUID } from "crypto";
22
+ //#region src/lib/auth-session-state.ts
23
+ /**
24
+ * Whether this run's OAuth grant is known to be dead.
25
+ *
26
+ * Process-global on purpose. A run has exactly one login, but the two sides of
27
+ * this fact are far apart: the pre-run refresh learns it in `authenticate.ts`,
28
+ * and the only consumer is the 401 handler inside the agent message loop, which
29
+ * holds no session. Threading it would mean a field on `AgentConfig` set at four
30
+ * `initializeAgent` call sites — and the session it would read from may be a
31
+ * shallow copy (`prepareRunSession`), so the value could be written to one
32
+ * object and read from another.
33
+ *
34
+ * A leaf module with no imports, so either side can depend on it without a cycle.
35
+ */
36
+ let grantRevoked = false;
37
+ /**
38
+ * Record that the token endpoint permanently refused this grant. Not an abort:
39
+ * the access token in hand may still have minutes of life, so the run continues
40
+ * and this only decides what a later 401 gets blamed on.
41
+ */
42
+ function markGrantRevoked() {
43
+ grantRevoked = true;
44
+ }
45
+ /** True once a token refresh failed because the grant itself is gone. */
46
+ function isGrantRevoked() {
47
+ return grantRevoked;
48
+ }
49
+ //#endregion
22
50
  //#region src/lib/gateway-session.ts
23
51
  /**
24
52
  * Gateway auth for a wizard run: a `phe_` scoped token the backend mints, with
@@ -84,6 +112,7 @@ async function resolveGatewayAuth(host, accessToken, key, program) {
84
112
  }
85
113
  const staleAtMs = Date.now() + ttlMs * REFRESH_AT_FRACTION;
86
114
  analytics.setTag("gateway_edition", "v2");
115
+ logToFile(`[gateway] minted a scoped token: program=${program} team=${minted.teamId ?? "unknown"} ttl=${Math.round(ttlMs / 1e3)}s url=${minted.gatewayUrl}`);
87
116
  const auth = {
88
117
  gatewayUrl: minted.gatewayUrl,
89
118
  token: minted.token,
@@ -2280,8 +2309,10 @@ function piRuntimeNotes(sequence, caps) {
2280
2309
  notes.push(YARA);
2281
2310
  if (linear) notes.push(SKILL_MENU, SKILL_STEPS);
2282
2311
  notes.push(NO_LITERAL_URL, ENV_VIA_MCP);
2283
- if (caps.posthogMcp) notes.push(POSTHOG_MCP);
2284
- if (linear) notes.push(DASHBOARD_STEP);
2312
+ if (caps.posthogMcp) {
2313
+ notes.push(POSTHOG_MCP);
2314
+ if (linear) notes.push(DASHBOARD_STEP);
2315
+ }
2285
2316
  notes.push(linear ? STATUS_LINEAR : STATUS_TASK);
2286
2317
  if (!linear) notes.push(COMPLETE_TASK);
2287
2318
  if (linear) notes.push(VERIFY_WITH_BUILD, DISPATCH_AGENT);
@@ -2860,6 +2891,22 @@ const hasStoredClaudeLogin = (login) => login.credentialsFile || login.keychain;
2860
2891
  */
2861
2892
  const claudeConfigDir = (homeDir = os.homedir()) => process.env.CLAUDE_CONFIG_DIR || path.join(homeDir, ".claude");
2862
2893
  /**
2894
+ * Create a fresh, empty config dir for the agent subprocess and return its path.
2895
+ * The spawn site sets it as `CLAUDE_CONFIG_DIR`, so the SDK's `claude` binary
2896
+ * resolves credentials from this empty dir — never the user's `~/.claude`. With
2897
+ * no `.credentials.json` to find, the binary cannot outrank the wizard's gateway
2898
+ * token (see {@link detectStoredClaudeLogin}), so a stored login can no longer
2899
+ * reach the PostHog gateway and 401.
2900
+ *
2901
+ * `mkdtempSync` gives each run its own dir, so concurrent runs never share one.
2902
+ * `/tmp` on macOS/Linux matches the agent sandbox's writable roots; Windows has
2903
+ * no `/tmp`, so fall back to the OS temp dir there.
2904
+ */
2905
+ function createIsolatedAgentConfigDir() {
2906
+ const base = process.platform === "win32" ? os.tmpdir() : "/tmp";
2907
+ return fs$1.mkdtempSync(path.join(base, "posthog-wizard-claude-"));
2908
+ }
2909
+ /**
2863
2910
  * Look for a stored Claude login. `homeDir` / `platform` are injectable for
2864
2911
  * tests; production uses the real home dir and platform.
2865
2912
  */
@@ -3145,7 +3192,7 @@ async function initializeAgent(config, options) {
3145
3192
  logToFile("API key prefix:", config.posthogApiKey ? `${config.posthogApiKey.slice(0, 4)}***` : "(missing)");
3146
3193
  const storedLogin = detectStoredClaudeLogin();
3147
3194
  if (hasStoredClaudeLogin(storedLogin)) {
3148
- logToFile(`Pre-existing Claude login detected (credentialsFile=${storedLogin.credentialsFile}, keychain=${storedLogin.keychain}). It can outrank the wizard's gateway token and cause a 401 — 'claude auth logout' clears it.`);
3195
+ logToFile(`Pre-existing Claude login detected (credentialsFile=${storedLogin.credentialsFile}, keychain=${storedLogin.keychain}). The isolated CLAUDE_CONFIG_DIR keeps it out of the agent run, so it no longer outranks the wizard's gateway token.`);
3149
3196
  analytics.wizardCapture("claude stored login detected", {
3150
3197
  credentials_file: storedLogin.credentialsFile,
3151
3198
  keychain: storedLogin.keychain
@@ -3154,7 +3201,7 @@ async function initializeAgent(config, options) {
3154
3201
  const initConflicts = checkAllSettingsConflicts(options.installDir);
3155
3202
  logToFile("Settings conflicts at agent init:", initConflicts.length > 0 ? initConflicts.map((c) => `${c.source}(${c.keys.join(",")})`).join("; ") : "none");
3156
3203
  const mcpServers = {
3157
- "posthog-wizard": {
3204
+ [POSTHOG_MCP_SERVER_NAME]: {
3158
3205
  type: "http",
3159
3206
  url: config.posthogMcpUrl,
3160
3207
  headers: {
@@ -3368,6 +3415,7 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
3368
3415
  ANTHROPIC_BASE_URL: agentConfig.gatewayAuth.gatewayUrl,
3369
3416
  ANTHROPIC_AUTH_TOKEN: agentConfig.gatewayAuth.token,
3370
3417
  CLAUDE_CODE_OAUTH_TOKEN: agentConfig.gatewayAuth.token,
3418
+ CLAUDE_CONFIG_DIR: createIsolatedAgentConfigDir(),
3371
3419
  CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: "true",
3372
3420
  POSTHOG_MCP_TOKEN: agentConfig.posthogApiKey,
3373
3421
  MCP_CONNECTION_NONBLOCKING: "0",
@@ -3451,19 +3499,25 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
3451
3499
  signalDone();
3452
3500
  spinner.stop("Authentication failed");
3453
3501
  const authError = buildAuthErrorContext(options.installDir, agentConfig.gatewayAuth.gatewayUrl, os.homedir(), signals.apiKeySource);
3502
+ const sessionExpired = isGrantRevoked();
3454
3503
  const authCode = classifyAuthFailure({
3455
3504
  hasSettingsConflict: authError.hasSettingsConflict,
3456
3505
  usingManagedLogin: authError.usingManagedLogin,
3506
+ sessionExpired,
3457
3507
  apiKey: options.apiKey,
3458
3508
  gatewayRegion: authError.region,
3459
3509
  sessionRegion: options.cloudRegion
3460
3510
  });
3461
- logToFile("Agent error: 401, showing auth error screen", authError);
3511
+ logToFile("Agent error: 401, showing auth error screen", {
3512
+ ...authError,
3513
+ sessionExpired
3514
+ });
3462
3515
  getUI().showAuthError({
3463
3516
  hasSettingsConflict: authError.hasSettingsConflict,
3464
3517
  conflicts: authError.conflicts,
3465
3518
  usingManagedLogin: authError.usingManagedLogin,
3466
3519
  credentialPlaces: authError.credentialPlaces,
3520
+ sessionExpired,
3467
3521
  logFilePath: getLogFilePath()
3468
3522
  });
3469
3523
  await wizardAbort({
@@ -3607,6 +3661,12 @@ let TaskTool = /* @__PURE__ */ function(TaskTool) {
3607
3661
  * `'Agent'` to opt into subagent dispatch). Skills and PostHog MCP tools
3608
3662
  * are enabled separately (skills option / mcpServers).
3609
3663
  */
3664
+ /**
3665
+ * The PostHog MCP server's name in `mcpServers`, and so the prefix of the tool
3666
+ * the agent calls it by (`mcp__posthog-wizard__exec`). Named once because the
3667
+ * init handler has to recognise this server in the SDK's status report.
3668
+ */
3669
+ const POSTHOG_MCP_SERVER_NAME = "posthog-wizard";
3610
3670
  const BASE_ALLOWED_TOOLS = [
3611
3671
  "Read",
3612
3672
  "Write",
@@ -3724,6 +3784,38 @@ function extractTokenUsageDelta(message) {
3724
3784
  model: apiMessage?.model
3725
3785
  };
3726
3786
  }
3787
+ /**
3788
+ * Report what the SDK did with our MCP servers, and capture it when the PostHog
3789
+ * one did not come up.
3790
+ *
3791
+ * The SDK connects `mcpServers` itself and drops a server it cannot reach — the
3792
+ * run continues, the tool is simply absent, and the agent finds out only by not
3793
+ * having it. What that looks like from outside is a run that collects every
3794
+ * credential and then tells the user to do the work by hand.
3795
+ *
3796
+ * The pi harness has captured `mcp setup failed` for a while (`harness/pi`), so
3797
+ * a pi run that lost the tool says so. The anthropic harness never did, even
3798
+ * though the SDK hands it a per-server verdict on the init message and this
3799
+ * code already had it in hand — it went to the log file and no further. A
3800
+ * warehouse run with zero creates therefore cost three investigations to
3801
+ * explain. The same event name and property shape as pi's, so one query covers
3802
+ * both harnesses.
3803
+ */
3804
+ function reportMcpSetup(message) {
3805
+ const servers = message.mcp_servers ?? [];
3806
+ const posthog = servers.find((s) => s.name === POSTHOG_MCP_SERVER_NAME);
3807
+ const toolPrefix = `mcp__${POSTHOG_MCP_SERVER_NAME}__`;
3808
+ const hasTool = (message.tools ?? []).some((t) => t.startsWith(toolPrefix));
3809
+ if (posthog?.status === "connected" && hasTool) return;
3810
+ const reason = !posthog ? "server missing from the SDK init report" : posthog.status !== "connected" ? `server status: ${posthog.status}` : "server connected but registered no tool";
3811
+ logToFile(`[anthropic] PostHog MCP unavailable — ${reason}`);
3812
+ analytics.wizardCapture("mcp setup failed", {
3813
+ harness: "anthropic",
3814
+ scope: "run",
3815
+ error: reason,
3816
+ mcp_servers: servers.map((s) => `${s.name}:${s.status}`).join(",")
3817
+ });
3818
+ }
3727
3819
  function handleSDKMessage(message, options, spinner, signals, receivedSuccessResult = false, tasks, suppressTaskRender = false, emitStepEvents = false, resolveStepKey) {
3728
3820
  const STATUS_RANK = {
3729
3821
  completed: 0,
@@ -3814,6 +3906,7 @@ function handleSDKMessage(message, options, spinner, signals, receivedSuccessRes
3814
3906
  mcpServers: message.mcp_servers,
3815
3907
  apiKeySource: message.apiKeySource
3816
3908
  });
3909
+ reportMcpSetup(message);
3817
3910
  }
3818
3911
  break;
3819
3912
  default:
@@ -3822,6 +3915,6 @@ function handleSDKMessage(message, options, spinner, signals, receivedSuccessRes
3822
3915
  }
3823
3916
  }
3824
3917
  //#endregion
3825
- export { installSkillById as A, MAX_ENV_KEY_SET as B, WIZARD_ASK_SUBJECT_DESCRIPTION as C, createAskAccounting as D, checkEnvKeys as E, templateEnvWriteRefusal as F, GATEWAY_PROVIDER as G, parseEnvKeyNames as H, vaultSensitiveAnswers as I, buildGatewayProvider as K, fetchWithRetry as L, normaliseAskSubject as M, resolveEnvPath as N, downloadSkill as O, resolveEnvSecretRefs as P, createWizardAskBridge as R, WIZARD_ASK_SENSITIVE_DESCRIPTION as S, WIZARD_TOOL_NAMES as T, toPromptSafeRelativePath as U, isEnvFileName as V, createTriageLLMProvider as W, PUBLISH_HANDOFF_TOOL_NAME as _, wizardCanUseTool as a, CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION as b, classifySettingsConflicts as c, sanitizeAgentSubprocessEnv as d, AgentOutputSignals as f, PUBLISH_HANDOFF_DESCRIPTION as g, PUBLISH_HANDOFF_CONTENT_DESCRIPTION as h, runAgent as i, mergeEnvValues as j, fetchSkillMenu as k, recoverOrphanedSettingsBackups as l, createSecretVault as m, buildRunTags as n, backupAndFixClaudeSettings as o, assembleCommandments as p, gatewayAuth as q, initializeAgent as r, checkAllSettingsConflicts as s, buildAgentEnv as t, restoreClaudeSettings as u, publishHandoff as v, WIZARD_ASK_TOOL_DESCRIPTION as w, ENV_FILE_PATH_DESCRIPTION as x, CHECK_ENV_KEYS_DESCRIPTION as y, isFullyCancelled as z };
3918
+ export { fetchSkillMenu as A, isFullyCancelled as B, WIZARD_ASK_SENSITIVE_DESCRIPTION as C, checkEnvKeys as D, WIZARD_TOOL_NAMES as E, resolveEnvSecretRefs as F, createTriageLLMProvider as G, isEnvFileName as H, templateEnvWriteRefusal as I, gatewayAuth as J, GATEWAY_PROVIDER as K, vaultSensitiveAnswers as L, mergeEnvValues as M, normaliseAskSubject as N, createAskAccounting as O, resolveEnvPath as P, fetchWithRetry as R, ENV_FILE_PATH_DESCRIPTION as S, WIZARD_ASK_TOOL_DESCRIPTION as T, parseEnvKeyNames as U, MAX_ENV_KEY_SET as V, toPromptSafeRelativePath as W, markGrantRevoked as Y, PUBLISH_HANDOFF_DESCRIPTION as _, wizardCanUseTool as a, CHECK_ENV_KEYS_DESCRIPTION as b, checkAllSettingsConflicts as c, restoreClaudeSettings as d, sanitizeAgentSubprocessEnv as f, PUBLISH_HANDOFF_CONTENT_DESCRIPTION as g, createSecretVault as h, runAgent as i, installSkillById as j, downloadSkill as k, classifySettingsConflicts as l, assembleCommandments as m, buildRunTags as n, createIsolatedAgentConfigDir as o, AgentOutputSignals as p, buildGatewayProvider as q, initializeAgent as r, backupAndFixClaudeSettings as s, buildAgentEnv as t, recoverOrphanedSettingsBackups as u, PUBLISH_HANDOFF_TOOL_NAME as v, WIZARD_ASK_SUBJECT_DESCRIPTION as w, CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION as x, publishHandoff as y, createWizardAskBridge as z };
3826
3919
 
3827
- //# sourceMappingURL=agent-interface-Lu7tnLr0.js.map
3920
+ //# sourceMappingURL=agent-interface-DFm4jB4d.js.map