(name: string, options: {
scope?: string;
})
| 72 | |
| 73 | // mcp remove (lines 4545–4635) |
| 74 | export async function mcpRemoveHandler(name: string, options: { |
| 75 | scope?: string; |
| 76 | }): Promise<void> { |
| 77 | // Look up config before removing so we can clean up secure storage |
| 78 | const serverBeforeRemoval = getMcpConfigByName(name); |
| 79 | const cleanupSecureStorage = () => { |
| 80 | if (serverBeforeRemoval && (serverBeforeRemoval.type === 'sse' || serverBeforeRemoval.type === 'http')) { |
| 81 | clearServerTokensFromLocalStorage(name, serverBeforeRemoval); |
| 82 | clearMcpClientConfig(name, serverBeforeRemoval); |
| 83 | } |
| 84 | }; |
| 85 | try { |
| 86 | if (options.scope) { |
| 87 | const scope = ensureConfigScope(options.scope); |
| 88 | logEvent('tengu_mcp_delete', { |
| 89 | name: name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 90 | scope: scope as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS |
| 91 | }); |
| 92 | await removeMcpConfig(name, scope); |
| 93 | cleanupSecureStorage(); |
| 94 | process.stdout.write(`Removed MCP server ${name} from ${scope} config\n`); |
| 95 | cliOk(`File modified: ${describeMcpConfigFilePath(scope)}`); |
| 96 | } |
| 97 | |
| 98 | // If no scope specified, check where the server exists |
| 99 | const projectConfig = getCurrentProjectConfig(); |
| 100 | const globalConfig = getGlobalConfig(); |
| 101 | |
| 102 | // Check if server exists in project scope (.mcp.json) |
| 103 | const { |
| 104 | servers: projectServers |
| 105 | } = getMcpConfigsByScope('project'); |
| 106 | const mcpJsonExists = !!projectServers[name]; |
| 107 | |
| 108 | // Count how many scopes contain this server |
| 109 | const scopes: Array<Exclude<ConfigScope, 'dynamic'>> = []; |
| 110 | if (projectConfig.mcpServers?.[name]) scopes.push('local'); |
| 111 | if (mcpJsonExists) scopes.push('project'); |
| 112 | if (globalConfig.mcpServers?.[name]) scopes.push('user'); |
| 113 | if (scopes.length === 0) { |
| 114 | cliError(`No MCP server found with name: "${name}"`); |
| 115 | } else if (scopes.length === 1) { |
| 116 | // Server exists in only one scope, remove it |
| 117 | const scope = scopes[0]!; |
| 118 | logEvent('tengu_mcp_delete', { |
| 119 | name: name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 120 | scope: scope as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS |
| 121 | }); |
| 122 | await removeMcpConfig(name, scope); |
| 123 | cleanupSecureStorage(); |
| 124 | process.stdout.write(`Removed MCP server "${name}" from ${scope} config\n`); |
| 125 | cliOk(`File modified: ${describeMcpConfigFilePath(scope)}`); |
| 126 | } else { |
| 127 | // Server exists in multiple scopes |
| 128 | process.stderr.write(`MCP server "${name}" exists in multiple scopes:\n`); |
| 129 | scopes.forEach(scope => { |
| 130 | process.stderr.write(` - ${getScopeLabel(scope)} (${describeMcpConfigFilePath(scope)})\n`); |
| 131 | }); |
no test coverage detected