// MCP Manager View
// Renders the MCP server management interface

// CCW Tools available for MCP
const CCW_MCP_TOOLS = [
  // Core tools (always recommended)
  { name: 'write_file', desc: 'Write/create files', core: true },
  { name: 'edit_file', desc: 'Edit/replace content', core: true },
  { name: 'smart_search', desc: 'Hybrid search (regex + semantic)', core: true },
  { name: 'core_memory', desc: 'Core memory management', core: true },
  // Optional tools
  { name: 'session_manager', desc: 'Workflow sessions', core: false },
  { name: 'generate_module_docs', desc: 'Generate docs', core: false },
  { name: 'update_module_claude', desc: 'Update CLAUDE.md', core: false },
  { name: 'cli_executor', desc: 'Gemini/Qwen/Codex CLI', core: false },
];

// Get currently enabled tools from installed config (Claude)
function getCcwEnabledTools() {
  const currentPath = projectPath; // Keep original format (forward slash)
  const projectData = mcpAllProjects[currentPath] || {};
  const ccwConfig = projectData.mcpServers?.['ccw-tools'];
  if (ccwConfig?.env?.CCW_ENABLED_TOOLS) {
    const val = ccwConfig.env.CCW_ENABLED_TOOLS;
    if (val.toLowerCase() === 'all') return CCW_MCP_TOOLS.map(t => t.name);
    return val.split(',').map(t => t.trim());
  }
  return CCW_MCP_TOOLS.filter(t => t.core).map(t => t.name);
}

// Get currently enabled tools from Codex config
function getCcwEnabledToolsCodex() {
  const ccwConfig = codexMcpServers?.['ccw-tools'];
  if (ccwConfig?.env?.CCW_ENABLED_TOOLS) {
    const val = ccwConfig.env.CCW_ENABLED_TOOLS;
    if (val.toLowerCase() === 'all') return CCW_MCP_TOOLS.map(t => t.name);
    return val.split(',').map(t => t.trim());
  }
  // Default to core tools if not installed
  return CCW_MCP_TOOLS.filter(t => t.core).map(t => t.name);
}

// Get current CCW_PROJECT_ROOT from config
function getCcwProjectRoot() {
  // Try project config first, then global config
  const currentPath = projectPath;
  const projectData = mcpAllProjects[currentPath] || {};
  const projectCcwConfig = projectData.mcpServers?.['ccw-tools'];
  if (projectCcwConfig?.env?.CCW_PROJECT_ROOT) {
    return projectCcwConfig.env.CCW_PROJECT_ROOT;
  }
  // Fallback to global config
  const globalCcwConfig = mcpUserServers?.['ccw-tools'];
  return globalCcwConfig?.env?.CCW_PROJECT_ROOT || '';
}

// Get current CCW_ALLOWED_DIRS from config
function getCcwAllowedDirs() {
  // Try project config first, then global config
  const currentPath = projectPath;
  const projectData = mcpAllProjects[currentPath] || {};
  const projectCcwConfig = projectData.mcpServers?.['ccw-tools'];
  if (projectCcwConfig?.env?.CCW_ALLOWED_DIRS) {
    return projectCcwConfig.env.CCW_ALLOWED_DIRS;
  }
  // Fallback to global config
  const globalCcwConfig = mcpUserServers?.['ccw-tools'];
  return globalCcwConfig?.env?.CCW_ALLOWED_DIRS || '';
}

// Get current CCW_PROJECT_ROOT from Codex config
function getCcwProjectRootCodex() {
  const ccwConfig = codexMcpServers?.['ccw-tools'];
  return ccwConfig?.env?.CCW_PROJECT_ROOT || '';
}

// Get current CCW_ALLOWED_DIRS from Codex config
function getCcwAllowedDirsCodex() {
  const ccwConfig = codexMcpServers?.['ccw-tools'];
  return ccwConfig?.env?.CCW_ALLOWED_DIRS || '';
}

async function renderMcpManager() {
  const container = document.getElementById('mainContent');
  if (!container) return;

  // Hide stats grid and search for MCP view
  const statsGrid = document.getElementById('statsGrid');
  const searchInput = document.getElementById('searchInput');
  if (statsGrid) statsGrid.style.display = 'none';
  if (searchInput) searchInput.parentElement.style.display = 'none';

  // Load MCP config if not already loaded
  if (!mcpConfig) {
    await loadMcpConfig();
  }

  // Load MCP templates
  await loadMcpTemplates();

  const currentPath = projectPath; // Keep original format (forward slash)
  const projectData = mcpAllProjects[currentPath] || {};
  const projectServers = projectData.mcpServers || {};
  const disabledServers = projectData.disabledMcpServers || [];
  const hasMcpJson = projectData.hasMcpJson || false;
  const mcpJsonPath = projectData.mcpJsonPath || null;

  // Get all available servers from all projects
  const allAvailableServers = getAllAvailableMcpServers();

  // Separate servers by category:
  // 1. Project Available = Global + Project-specific (servers available to current project)
  // 2. Global Management = Global servers that can be managed
  // 3. Other Projects = Servers from other projects (can install to project or global)

  const currentProjectServerNames = Object.keys(projectServers);
  const globalServerNames = Object.keys(mcpUserServers || {});
  const enterpriseServerNames = Object.keys(mcpEnterpriseServers || {});

  // Project Available MCP: servers available to current project
  // This includes: Enterprise (highest priority) + Global + Project-specific
  const projectAvailableEntries = [];

  // Add enterprise servers first (highest priority)
  for (const [name, config] of Object.entries(mcpEnterpriseServers || {})) {
    projectAvailableEntries.push({
      name,
      config,
      source: 'enterprise',
      canRemove: false,
      canToggle: false
    });
  }

  // Add global servers
  for (const [name, config] of Object.entries(mcpUserServers || {})) {
    if (!enterpriseServerNames.includes(name)) {
      projectAvailableEntries.push({
        name,
        config,
        source: 'global',
        canRemove: false, // Can't remove from project view, must go to global management
        canToggle: true,
        isEnabled: !disabledServers.includes(name)
      });
    }
  }

  // Add project-specific servers
  for (const [name, config] of Object.entries(projectServers)) {
    if (!enterpriseServerNames.includes(name) && !globalServerNames.includes(name)) {
      projectAvailableEntries.push({
        name,
        config,
        source: 'project',
        canRemove: true,
        canToggle: true,
        isEnabled: !disabledServers.includes(name)
      });
    }
  }

  // Global Management: user global servers (for management)
  const globalManagementEntries = Object.entries(mcpUserServers || {});

  // Enterprise servers (for display only, read-only)
  const enterpriseServerEntries = Object.entries(mcpEnterpriseServers || {});

  // Other Projects: servers from other projects (not in current project, not global)
  const otherProjectServers = Object.entries(allAvailableServers)
    .filter(([name, info]) => !currentProjectServerNames.includes(name) && !info.isGlobal);
  // Check if CCW Tools is already installed
  const isCcwToolsInstalled = currentProjectServerNames.includes("ccw-tools");
  const enabledTools = getCcwEnabledTools();
  const enabledToolsCodex = getCcwEnabledToolsCodex();

  // Prepare Codex servers data
  const codexServerEntries = Object.entries(codexMcpServers || {});
  const codexConfigExists = codexMcpConfig?.exists || false;
  const codexConfigPath = codexMcpConfig?.configPath || '~/.codex/config.toml';

  // Collect cross-CLI servers (servers from other CLI not yet in current CLI)
  const crossCliServers = [];
  if (currentCliMode === 'claude') {
    // In Claude mode, show Codex servers that aren't in Claude
    for (const [name, config] of Object.entries(codexMcpServers || {})) {
      const existsInClaude = currentProjectServerNames.includes(name) || globalServerNames.includes(name);
      if (!existsInClaude) {
        crossCliServers.push({ name, config, fromCli: 'codex' });
      }
    }
  } else {
    // In Codex mode, show Claude servers that aren't in Codex
    const allClaudeServers = { ...mcpUserServers, ...projectServers };
    for (const [name, config] of Object.entries(allClaudeServers)) {
      const existsInCodex = codexMcpServers && codexMcpServers[name];
      if (!existsInCodex) {
        crossCliServers.push({ name, config, fromCli: 'claude' });
      }
    }
  }

  container.innerHTML = `
    <div class="mcp-manager">
      <!-- CLI Mode Toggle -->
      <div class="mcp-cli-toggle mb-6">
        <div class="flex items-center justify-between bg-card border border-border rounded-lg p-4">
          <div class="flex items-center gap-3">
            <span class="text-sm font-medium text-foreground">${t('mcp.cliMode')}</span>
            <div class="flex items-center bg-muted rounded-lg p-1">
              <button class="cli-mode-btn px-4 py-2 text-sm font-medium rounded-md transition-all ${currentCliMode === 'claude' ? 'bg-primary text-primary-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
                      onclick="setCliMode('claude')">
                <i data-lucide="bot" class="w-4 h-4 inline mr-1.5"></i>
                Claude
              </button>
              <button class="cli-mode-btn px-4 py-2 text-sm font-medium rounded-md transition-all ${currentCliMode === 'codex' ? 'shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
                      onclick="setCliMode('codex')"
                      style="${currentCliMode === 'codex' ? 'background-color: #f97316; color: white;' : ''}">
                <i data-lucide="code-2" class="w-4 h-4 inline mr-1.5"></i>
                Codex
              </button>
            </div>
          </div>
          <div class="text-xs text-muted-foreground">
            ${currentCliMode === 'claude'
              ? `<span class="flex items-center gap-1"><i data-lucide="file-json" class="w-3 h-3"></i> ~/.claude.json</span>`
              : `<span class="flex items-center gap-1"><i data-lucide="file-code" class="w-3 h-3"></i> ${codexConfigPath}</span>`
            }
          </div>
        </div>
      </div>

      ${currentCliMode === 'codex' ? `
      <!-- CCW Tools MCP Server Card (Codex mode) -->
      <div class="mcp-section mb-6">
        <div class="ccw-tools-card bg-gradient-to-br from-primary/10 to-primary/5 border-2 ${codexMcpServers && codexMcpServers['ccw-tools'] ? 'border-success' : 'border-primary/30'} rounded-lg p-6 hover:shadow-lg transition-all">
          <div class="flex items-start justify-between gap-4">
            <div class="flex items-start gap-4 flex-1">
              <div class="shrink-0 w-12 h-12 bg-primary rounded-lg flex items-center justify-center">
                <i data-lucide="wrench" class="w-6 h-6 text-white"></i>
              </div>
              <div class="flex-1 min-w-0">
                <div class="flex items-center gap-2 mb-2">
                  <h3 class="text-lg font-bold text-foreground">CCW Tools MCP</h3>
                  <span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">Codex</span>
                  ${codexMcpServers && codexMcpServers['ccw-tools'] ? `
                    <span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-success-light text-success">
                      <i data-lucide="check" class="w-3 h-3"></i>
                      ${enabledToolsCodex.length} tools
                    </span>
                  ` : `
                    <span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-primary/20 text-primary">
                      <i data-lucide="package" class="w-3 h-3"></i>
                      ${t('mcp.available')}
                    </span>
                  `}
                </div>
                <p class="text-sm text-muted-foreground mb-3">${t('mcp.ccwToolsDesc')}</p>
                <!-- Tool Selection Grid for Codex -->
                <div class="grid grid-cols-3 sm:grid-cols-5 gap-2 mb-3">
                  ${CCW_MCP_TOOLS.map(tool => `
                    <label class="flex items-center gap-1.5 text-xs cursor-pointer hover:bg-muted/50 rounded px-1.5 py-1 transition-colors">
                      <input type="checkbox" class="ccw-tool-checkbox-codex w-3 h-3"
                             data-tool="${tool.name}"
                             ${enabledToolsCodex.includes(tool.name) ? 'checked' : ''}>
                      <span class="${tool.core ? 'font-medium' : 'text-muted-foreground'}">${tool.desc}</span>
                    </label>
                  `).join('')}
                </div>
                <div class="flex items-center gap-3 text-xs">
                  <button class="text-primary hover:underline" onclick="selectCcwToolsCodex('core')">Core only</button>
                  <button class="text-primary hover:underline" onclick="selectCcwToolsCodex('all')">All</button>
                  <button class="text-muted-foreground hover:underline" onclick="selectCcwToolsCodex('none')">None</button>
                </div>
                <!-- Path Settings -->
                <div class="ccw-path-settings mt-3 pt-3 border-t border-border/50">
                  <div class="flex items-center gap-2 mb-2">
                    <i data-lucide="folder-root" class="w-4 h-4 text-muted-foreground"></i>
                    <span class="text-xs font-medium text-muted-foreground">${t('mcp.pathSettings')}</span>
                  </div>
                  <div class="grid grid-cols-1 gap-2">
                    <div class="flex items-center gap-2">
                      <label class="text-xs text-muted-foreground w-36 shrink-0">CCW_PROJECT_ROOT</label>
                      <input type="text"
                             class="ccw-project-root-input flex-1 px-2 py-1 text-xs bg-background border border-border rounded focus:outline-none focus:ring-1 focus:ring-primary"
                             placeholder="${projectPath || t('mcp.useCurrentDir')}"
                             value="${getCcwProjectRootCodex()}">
                      <button class="p-1 text-muted-foreground hover:text-foreground"
                              onclick="setCcwProjectRootToCurrent()"
                              title="${t('mcp.useCurrentProject')}">
                        <i data-lucide="locate-fixed" class="w-4 h-4"></i>
                      </button>
                    </div>
                    <div class="flex items-center gap-2">
                      <label class="text-xs text-muted-foreground w-36 shrink-0">CCW_ALLOWED_DIRS</label>
                      <input type="text"
                             class="ccw-allowed-dirs-input flex-1 px-2 py-1 text-xs bg-background border border-border rounded focus:outline-none focus:ring-1 focus:ring-primary"
                             placeholder="${t('mcp.allowedDirsPlaceholder')}"
                             value="${getCcwAllowedDirsCodex()}">
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div class="shrink-0">
              <button class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                      data-action="install-ccw-codex">
                <i data-lucide="download" class="w-4 h-4"></i>
                ${codexMcpServers && codexMcpServers['ccw-tools'] ? t('mcp.update') : t('mcp.install')}
              </button>
            </div>
          </div>
        </div>
      </div>

      <!-- Codex MCP Servers Section -->
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <div class="flex items-center gap-3">
            <div class="flex items-center gap-2">
              <i data-lucide="code-2" class="w-5 h-5 text-primary"></i>
              <h3 class="text-lg font-semibold text-foreground">${t('mcp.codex.globalServers')}</h3>
            </div>
            <button class="px-3 py-1.5 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                    onclick="openCodexMcpCreateModal()">
              <span>+</span> ${t('mcp.codex.newServer')}
            </button>
            ${codexConfigExists ? `
              <span class="inline-flex items-center gap-1.5 px-2 py-1 text-xs bg-success/10 text-success rounded-md border border-success/20">
                <i data-lucide="file-check" class="w-3.5 h-3.5"></i>
                config.toml
              </span>
            ` : `
              <span class="inline-flex items-center gap-1.5 px-2 py-1 text-xs bg-muted text-muted-foreground rounded-md border border-border" title="Will create ~/.codex/config.toml">
                <i data-lucide="file-plus" class="w-3.5 h-3.5"></i>
                Will create config.toml
              </span>
            `}
          </div>
          <span class="text-sm text-muted-foreground">${codexServerEntries.length} ${t('mcp.serversAvailable')}</span>
        </div>

        <!-- Info about Codex MCP -->
        <div class="bg-green-50 dark:bg-green-950/30 border border-primary/20 rounded-lg p-4 mb-4">
          <div class="flex items-start gap-3">
            <i data-lucide="info" class="w-5 h-5 text-green-500 shrink-0 mt-0.5"></i>
            <div class="text-sm">
              <p class="text-primary font-medium mb-1">${t('mcp.codex.infoTitle')}</p>
              <p class="text-primary/80 text-xs">${t('mcp.codex.infoDesc')}</p>
            </div>
          </div>
        </div>

        ${codexServerEntries.length === 0 ? `
          <div class="mcp-empty-state bg-card border border-border rounded-lg p-6 text-center">
            <div class="text-muted-foreground mb-3"><i data-lucide="plug" class="w-10 h-10 mx-auto"></i></div>
            <p class="text-muted-foreground">${t('mcp.codex.noServers')}</p>
            <p class="text-sm text-muted-foreground mt-1">${t('mcp.codex.noServersHint')}</p>
          </div>
        ` : `
          <div class="mcp-server-grid grid gap-3">
            ${codexServerEntries.map(([serverName, serverConfig]) => {
              return renderCodexServerCard(serverName, serverConfig);
            }).join('')}
          </div>
        `}
      </div>

      <!-- Copy Claude Servers to Codex -->
      ${Object.keys(mcpUserServers || {}).length > 0 ? `
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground flex items-center gap-2">
            <i data-lucide="copy" class="w-5 h-5"></i>
            ${t('mcp.codex.copyFromClaude')}
          </h3>
          <span class="text-sm text-muted-foreground">${Object.keys(mcpUserServers || {}).length} ${t('mcp.serversAvailable')}</span>
        </div>
        <div class="mcp-server-grid grid gap-3">
          ${Object.entries(mcpUserServers || {}).map(([serverName, serverConfig]) => {
            const alreadyInCodex = codexMcpServers && codexMcpServers[serverName];
            return `
              <div class="mcp-server-card bg-card border ${alreadyInCodex ? 'border-success/50' : 'border-border'} border-dashed rounded-lg p-4 hover:shadow-md transition-all">
                <div class="flex items-start justify-between mb-3">
                  <div class="flex items-center gap-2">
                    <i data-lucide="bot" class="w-5 h-5 text-primary"></i>
                    <h4 class="font-semibold text-foreground">${escapeHtml(serverName)}</h4>
                    <span class="text-xs px-2 py-0.5 bg-primary/10 text-primary rounded-full">Claude</span>
                    ${alreadyInCodex ? `<span class="text-xs px-2 py-0.5 bg-success/10 text-success rounded-full">${t('mcp.codex.alreadyAdded')}</span>` : ''}
                  </div>
                  ${!alreadyInCodex ? `
                    <button class="px-3 py-1 text-xs bg-primary text-primary-foreground rounded hover:opacity-90 transition-opacity"
                            data-action="copy-to-codex"
                            data-server-name="${escapeHtml(serverName)}"
                            data-server-config="${encodeConfigData(serverConfig)}"
                            title="${t('mcp.codex.copyToCodex')}">
                      <i data-lucide="arrow-right" class="w-3.5 h-3.5 inline"></i> Codex
                    </button>
                  ` : ''}
                </div>
                <div class="mcp-server-details text-sm space-y-1">
                  <div class="flex items-center gap-2 text-muted-foreground">
                    <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.cmd')}</span>
                    <span class="truncate" title="${escapeHtml(serverConfig.command || 'N/A')}">${escapeHtml(serverConfig.command || 'N/A')}</span>
                  </div>
                </div>
              </div>
            `;
          }).join('')}
        </div>
      </div>
      ` : ''}

      <!-- Available MCP Servers from Other Projects (Codex mode) -->
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground">${t('mcp.availableOther')}</h3>
          <span class="text-sm text-muted-foreground">${otherProjectServers.length} ${t('mcp.serversAvailable')}</span>
        </div>

        ${otherProjectServers.length === 0 ? `
          <div class="mcp-empty-state bg-card border border-border rounded-lg p-6 text-center">
            <p class="text-muted-foreground">${t('empty.noAdditionalMcp')}</p>
          </div>
        ` : `
          <div class="mcp-server-grid grid gap-3">
            ${otherProjectServers.map(([serverName, serverInfo]) => {
              return renderAvailableServerCardForCodex(serverName, serverInfo);
            }).join('')}
          </div>
        `}
      </div>

      <!-- Cross-CLI Servers: Available from Claude (Codex mode) -->
      ${crossCliServers.length > 0 ? `
      <div class="mcp-section">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground flex items-center gap-2">
            <i data-lucide="circle" class="w-5 h-5 text-primary"></i>
            ${t('mcp.codex.copyFromClaude')}
          </h3>
          <span class="text-sm text-muted-foreground">${crossCliServers.length} ${t('mcp.serversAvailable')}</span>
        </div>
        <div class="mcp-server-grid grid gap-3">
          ${crossCliServers.map(server => renderCrossCliServerCard(server, false)).join('')}
        </div>
      </div>
      ` : ''}
      ` : `
      <!-- CCW Tools MCP Server Card -->
      <div class="mcp-section mb-6">
        <div class="ccw-tools-card bg-gradient-to-br from-primary/10 to-primary/5 border-2 ${isCcwToolsInstalled ? 'border-success' : 'border-primary/30'} rounded-lg p-6 hover:shadow-lg transition-all">
          <div class="flex items-start justify-between gap-4">
            <div class="flex items-start gap-4 flex-1">
              <div class="shrink-0 w-12 h-12 bg-primary rounded-lg flex items-center justify-center">
                <i data-lucide="wrench" class="w-6 h-6 text-white"></i>
              </div>
              <div class="flex-1 min-w-0">
                <div class="flex items-center gap-2 mb-2">
                  <h3 class="text-lg font-bold text-foreground">CCW Tools MCP</h3>
                  ${isCcwToolsInstalled ? `
                    <span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-success-light text-success">
                      <i data-lucide="check" class="w-3 h-3"></i>
                      ${enabledTools.length} tools
                    </span>
                  ` : `
                    <span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-primary/20 text-primary">
                      <i data-lucide="package" class="w-3 h-3"></i>
                      Available
                    </span>
                  `}
                </div>
                <!-- Tool Selection Grid -->
                <div class="grid grid-cols-3 sm:grid-cols-5 gap-2 mb-3">
                  ${CCW_MCP_TOOLS.map(tool => `
                    <label class="flex items-center gap-1.5 text-xs cursor-pointer hover:bg-muted/50 rounded px-1.5 py-1 transition-colors">
                      <input type="checkbox" class="ccw-tool-checkbox w-3 h-3"
                             data-tool="${tool.name}"
                             ${enabledTools.includes(tool.name) ? 'checked' : ''}>
                      <span class="${tool.core ? 'font-medium' : 'text-muted-foreground'}">${tool.desc}</span>
                    </label>
                  `).join('')}
                </div>
                <div class="flex items-center gap-3 text-xs">
                  <button class="text-primary hover:underline" onclick="selectCcwTools('core')">Core only</button>
                  <button class="text-primary hover:underline" onclick="selectCcwTools('all')">All</button>
                  <button class="text-muted-foreground hover:underline" onclick="selectCcwTools('none')">None</button>
                </div>
                <!-- Path Settings -->
                <div class="ccw-path-settings mt-3 pt-3 border-t border-border/50">
                  <div class="flex items-center gap-2 mb-2">
                    <i data-lucide="folder-root" class="w-4 h-4 text-muted-foreground"></i>
                    <span class="text-xs font-medium text-muted-foreground">${t('mcp.pathSettings')}</span>
                  </div>
                  <div class="grid grid-cols-1 gap-2">
                    <div class="flex items-center gap-2">
                      <label class="text-xs text-muted-foreground w-36 shrink-0">CCW_PROJECT_ROOT</label>
                      <input type="text"
                             class="ccw-project-root-input flex-1 px-2 py-1 text-xs bg-background border border-border rounded focus:outline-none focus:ring-1 focus:ring-primary"
                             placeholder="${projectPath || t('mcp.useCurrentDir')}"
                             value="${getCcwProjectRoot()}">
                      <button class="p-1 text-muted-foreground hover:text-foreground"
                              onclick="setCcwProjectRootToCurrent()"
                              title="${t('mcp.useCurrentProject')}">
                        <i data-lucide="locate-fixed" class="w-4 h-4"></i>
                      </button>
                    </div>
                    <div class="flex items-center gap-2">
                      <label class="text-xs text-muted-foreground w-36 shrink-0">CCW_ALLOWED_DIRS</label>
                      <input type="text"
                             class="ccw-allowed-dirs-input flex-1 px-2 py-1 text-xs bg-background border border-border rounded focus:outline-none focus:ring-1 focus:ring-primary"
                             placeholder="${t('mcp.allowedDirsPlaceholder')}"
                             value="${getCcwAllowedDirs()}">
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div class="shrink-0 flex gap-2">
              ${isCcwToolsInstalled ? `
                <button class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                        data-action="update-ccw-workspace"
                        title="${t('mcp.updateInWorkspace')}">
                  <i data-lucide="folder" class="w-4 h-4"></i>
                  ${t('mcp.updateInWorkspace')}
                </button>
                <button class="px-4 py-2 text-sm bg-success text-success-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                        data-action="update-ccw-global"
                        title="${t('mcp.updateInGlobal')}">
                  <i data-lucide="globe" class="w-4 h-4"></i>
                  ${t('mcp.updateInGlobal')}
                </button>
              ` : `
                <button class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                        data-action="install-ccw-workspace"
                        title="${t('mcp.installToWorkspace')}">
                  <i data-lucide="folder" class="w-4 h-4"></i>
                  ${t('mcp.installToWorkspace')}
                </button>
                <button class="px-4 py-2 text-sm bg-success text-success-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                        data-action="install-ccw-global"
                        title="${t('mcp.installToGlobal')}">
                  <i data-lucide="globe" class="w-4 h-4"></i>
                  ${t('mcp.installToGlobal')}
                </button>
              `}
            </div>
          </div>
        </div>
      </div>

      <!-- Project Available MCP Servers -->
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <div class="flex items-center gap-3">
            <h3 class="text-lg font-semibold text-foreground">${t('mcp.projectAvailable')}</h3>
            <button class="px-3 py-1.5 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                    onclick="openMcpCreateModal('project')">
              <span>+</span> ${t('mcp.newProjectServer')}
            </button>
            <!-- Project Config Type Toggle -->
            <button class="project-config-toggle inline-flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-lg border cursor-pointer transition-all hover:shadow-md"
                    onclick="toggleProjectConfigType()"
                    title="${t('mcp.clickToSwitch')}"
                    style="${getPreferredProjectConfigType() === 'mcp'
                      ? 'background: rgba(34, 197, 94, 0.1); border-color: rgba(34, 197, 94, 0.3); color: rgb(34, 197, 94);'
                      : 'background: rgba(59, 130, 246, 0.1); border-color: rgba(59, 130, 246, 0.3); color: rgb(59, 130, 246);'}">
              <i data-lucide="${getPreferredProjectConfigType() === 'mcp' ? 'file-json' : 'settings'}" class="w-3.5 h-3.5"></i>
              <span>${getPreferredProjectConfigType() === 'mcp' ? '.mcp.json' : 'claude.json'}</span>
              <i data-lucide="chevrons-up-down" class="w-3 h-3 opacity-50"></i>
            </button>
            ${hasMcpJson ? `
              <span class="inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] bg-success/10 text-success rounded border border-success/20">
                <i data-lucide="check" class="w-2.5 h-2.5"></i>
                exists
              </span>
            ` : ''}
          </div>
          <span class="text-sm text-muted-foreground">${projectAvailableEntries.length} ${t('mcp.serversAvailable')}</span>
        </div>

        ${projectAvailableEntries.length === 0 ? `
          <div class="mcp-empty-state bg-card border border-border rounded-lg p-6 text-center">
            <div class="text-muted-foreground mb-3"><i data-lucide="plug" class="w-10 h-10 mx-auto"></i></div>
            <p class="text-muted-foreground">${t('empty.noMcpServers')}</p>
            <p class="text-sm text-muted-foreground mt-1">${t('empty.addMcpServersHint')}</p>
          </div>
        ` : `
          <div class="mcp-server-grid grid gap-3">
            ${projectAvailableEntries.map(entry => {
              return renderProjectAvailableServerCard(entry);
            }).join('')}
          </div>
        `}
      </div>

      <!-- Global Available MCP Servers -->
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <div class="flex items-center gap-3">
            <div class="flex items-center gap-2">
              <i data-lucide="globe" class="w-5 h-5 text-success"></i>
              <h3 class="text-lg font-semibold text-foreground">${t('mcp.globalAvailable')}</h3>
            </div>
            <button class="px-3 py-1.5 text-sm bg-success text-success-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
                    onclick="openMcpCreateModal('global')">
              <span>+</span> ${t('mcp.newGlobalServer')}
            </button>
          </div>
          <span class="text-sm text-muted-foreground">${globalManagementEntries.length} ${t('mcp.globalServersFrom')}</span>
        </div>

        ${globalManagementEntries.length === 0 ? `
          <div class="mcp-empty-state bg-card border border-border rounded-lg p-6 text-center">
            <div class="text-muted-foreground mb-3"><i data-lucide="globe" class="w-10 h-10 mx-auto"></i></div>
            <p class="text-muted-foreground">${t('empty.noGlobalMcpServers')}</p>
            <p class="text-sm text-muted-foreground mt-1">${t('empty.globalServersHint')}</p>
          </div>
        ` : `
          <div class="mcp-server-grid grid gap-3">
            ${globalManagementEntries.map(([serverName, serverConfig]) => {
              return renderGlobalManagementCard(serverName, serverConfig);
            }).join('')}
          </div>
        `}
      </div>

      <!-- Available MCP Servers from Other Projects -->
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground">${t('mcp.availableOther')}</h3>
          <span class="text-sm text-muted-foreground">${otherProjectServers.length} ${t('mcp.serversAvailable')}</span>
        </div>

        ${otherProjectServers.length === 0 ? `
          <div class="mcp-empty-state bg-card border border-border rounded-lg p-6 text-center">
            <p class="text-muted-foreground">${t('empty.noAdditionalMcp')}</p>
          </div>
        ` : `
          <div class="mcp-server-grid grid gap-3">
            ${otherProjectServers.map(([serverName, serverInfo]) => {
              return renderAvailableServerCard(serverName, serverInfo);
            }).join('')}
          </div>
        `}
      </div>

      <!-- Cross-CLI Servers: Available from Codex (Claude mode) -->
      ${crossCliServers.length > 0 ? `
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground flex items-center gap-2">
            <i data-lucide="circle-dashed" class="w-5 h-5 text-primary"></i>
            ${t('mcp.claude.copyFromCodex')}
          </h3>
          <span class="text-sm text-muted-foreground">${crossCliServers.length} ${t('mcp.serversAvailable')}</span>
        </div>
        <div class="mcp-server-grid grid gap-3">
          ${crossCliServers.map(server => renderCrossCliServerCard(server, true)).join('')}
        </div>
      </div>
      ` : ''}

      <!-- MCP Templates Section -->
      ${mcpTemplates.length > 0 ? `
      <div class="mcp-section mt-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground flex items-center gap-2">
            <i data-lucide="layout-template" class="w-5 h-5"></i>
            ${t('mcp.templates')}
          </h3>
          <span class="text-sm text-muted-foreground">${mcpTemplates.length} ${t('mcp.savedTemplates')}</span>
        </div>

        <div class="mcp-server-grid grid gap-3">
          ${mcpTemplates.map(template => `
            <div class="mcp-template-card mcp-server-card bg-card border border-border border-dashed rounded-lg p-4 hover:shadow-md hover:border-solid transition-all">
              <div class="flex items-start justify-between mb-3">
                <div class="flex items-center gap-2 flex-wrap">
                  <span><i data-lucide="layout-template" class="w-5 h-5 text-muted-foreground"></i></span>
                  <h4 class="font-semibold text-foreground">${escapeHtml(template.name)}</h4>
                  ${template.description ? `
                    <span class="text-xs px-2 py-0.5 bg-muted text-muted-foreground rounded-full truncate max-w-32" title="${escapeHtml(template.description)}">
                      ${escapeHtml(template.description)}
                    </span>
                  ` : ''}
                </div>
                <div class="flex gap-2">
                  <button class="px-3 py-1 text-xs bg-primary text-primary-foreground rounded hover:opacity-90 transition-opacity"
                          data-template-name="${escapeHtml(template.name)}"
                          data-scope="project"
                          data-action="install-template"
                          title="${t('mcp.installToProject')}">
                    <i data-lucide="folder-plus" class="w-3.5 h-3.5 inline"></i>
                  </button>
                  <button class="px-3 py-1 text-xs bg-success text-success-foreground rounded hover:opacity-90 transition-opacity"
                          data-template-name="${escapeHtml(template.name)}"
                          data-scope="global"
                          data-action="install-template"
                          title="${t('mcp.installToGlobal')}">
                    <i data-lucide="globe" class="w-3.5 h-3.5 inline"></i>
                  </button>
                </div>
              </div>

              <div class="mcp-server-details text-sm space-y-1">
                <div class="flex items-center gap-2 text-muted-foreground">
                  <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.cmd')}</span>
                  <span class="truncate" title="${escapeHtml(template.serverConfig.command)}">${escapeHtml(template.serverConfig.command)}</span>
                </div>
                ${template.serverConfig.args && template.serverConfig.args.length > 0 ? `
                  <div class="flex items-start gap-2 text-muted-foreground">
                    <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
                    <span class="text-xs font-mono truncate" title="${escapeHtml(template.serverConfig.args.join(' '))}">${escapeHtml(template.serverConfig.args.slice(0, 3).join(' '))}${template.serverConfig.args.length > 3 ? '...' : ''}</span>
                  </div>
                ` : ''}
              </div>

              <div class="mt-3 pt-3 border-t border-border flex items-center justify-between gap-2">
                <div class="flex items-center gap-2">
                  <button class="text-xs text-primary hover:text-primary/80 transition-colors flex items-center gap-1"
                          data-template-name="${escapeHtml(template.name)}"
                          data-scope="project"
                          data-action="install-template"
                          title="${t('mcp.installToProject')}">
                    <i data-lucide="download" class="w-3 h-3"></i>
                    ${t('mcp.toProject')}
                  </button>
                  <button class="text-xs text-success hover:text-success/80 transition-colors flex items-center gap-1"
                          data-template-name="${escapeHtml(template.name)}"
                          data-scope="global"
                          data-action="install-template"
                          title="${t('mcp.installToGlobal')}">
                    <i data-lucide="globe" class="w-3 h-3"></i>
                    ${t('mcp.toGlobal')}
                  </button>
                </div>
                <button class="text-xs text-destructive hover:text-destructive/80 transition-colors"
                        data-template-name="${escapeHtml(template.name)}"
                        data-action="delete-template"
                        title="${t('mcp.deleteTemplate')}">
                  <i data-lucide="trash-2" class="w-3 h-3"></i>
                </button>
              </div>
            </div>
          `).join('')}
        </div>
      </div>
      ` : ''}

      <!-- Copy Codex Servers to Claude (Claude mode only) -->
      ${currentCliMode === 'claude' && Object.keys(codexMcpServers || {}).length > 0 ? `
      <div class="mcp-section mb-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground flex items-center gap-2">
            <i data-lucide="copy" class="w-5 h-5"></i>
            ${t('mcp.claude.copyFromCodex')}
          </h3>
          <span class="text-sm text-muted-foreground">${Object.keys(codexMcpServers || {}).length} ${t('mcp.serversAvailable')}</span>
        </div>
        <div class="mcp-server-grid grid gap-3">
          ${Object.entries(codexMcpServers || {}).map(([serverName, serverConfig]) => {
            const alreadyInClaude = mcpUserServers && mcpUserServers[serverName];
            const isStdio = !!serverConfig.command;
            const isHttp = !!serverConfig.url;
            return `
              <div class="mcp-server-card bg-card border ${alreadyInClaude ? 'border-success/50' : 'border-primary/20'} border-dashed rounded-lg p-4 hover:shadow-md transition-all">
                <div class="flex items-start justify-between mb-3">
                  <div class="flex items-center gap-2 flex-wrap">
                    <i data-lucide="code-2" class="w-5 h-5 text-primary"></i>
                    <h4 class="font-semibold text-foreground">${escapeHtml(serverName)}</h4>
                    <span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">Codex</span>
                    ${isHttp
                      ? '<span class="text-xs px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300 rounded-full">HTTP</span>'
                      : '<span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">STDIO</span>'
                    }
                    ${alreadyInClaude ? '<span class="text-xs px-2 py-0.5 bg-success/10 text-success rounded-full">' + t('mcp.claude.alreadyAdded') + '</span>' : ''}
                  </div>
                  ${!alreadyInClaude ? `
                    <button class="px-3 py-1 text-xs bg-primary text-primary-foreground rounded hover:opacity-90 transition-opacity"
                            data-action="copy-codex-to-claude"
                            data-server-name="${escapeHtml(serverName)}"
                            data-server-config="${encodeConfigData(serverConfig)}"
                            title="${t('mcp.claude.copyToClaude')}">
                      <i data-lucide="arrow-right" class="w-3.5 h-3.5 inline"></i> Claude
                    </button>
                  ` : ''}
                </div>
                <div class="mcp-server-details text-sm space-y-1">
                  <div class="flex items-center gap-2 text-muted-foreground">
                    <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${isHttp ? t('mcp.url') : t('mcp.cmd')}</span>
                    <span class="truncate" title="${escapeHtml(serverConfig.command || serverConfig.url || 'N/A')}">${escapeHtml(serverConfig.command || serverConfig.url || 'N/A')}</span>
                  </div>
                </div>
              </div>
            `;
          }).join('')}
        </div>
      </div>
      ` : ''}

      <!-- All Projects MCP Overview Table (Claude mode only) -->
      ${currentCliMode === 'claude' ? `
      <div class="mcp-section mt-6">
        <div class="flex items-center justify-between mb-4">
          <h3 class="text-lg font-semibold text-foreground">${t('mcp.allProjects')}</h3>
          <span class="text-sm text-muted-foreground">${Object.keys(mcpAllProjects).length} ${t('mcp.projects')}</span>
        </div>

        <div class="mcp-projects-table bg-card border border-border rounded-lg overflow-hidden">
          <table class="w-full">
            <thead class="bg-muted/50">
              <tr>
                <th class="text-left px-4 py-3 text-sm font-semibold text-foreground border-b border-border">${t('mcp.project')}</th>
                <th class="text-left px-4 py-3 text-sm font-semibold text-foreground border-b border-border">${t('mcp.servers')}</th>
                <th class="text-center px-4 py-3 text-sm font-semibold text-foreground border-b border-border w-24">${t('mcp.status')}</th>
              </tr>
            </thead>
            <tbody>
              ${Object.entries(mcpAllProjects).map(([path, config]) => {
                const servers = config.mcpServers || {};
                const projectDisabled = config.disabledMcpServers || [];
                const serverNames = Object.keys(servers);
                const isCurrentProject = path === currentPath;
                const enabledCount = serverNames.filter(s => !projectDisabled.includes(s)).length;
                const projectHasMcpJson = config.hasMcpJson || false;

                return `
                  <tr class="border-b border-border last:border-b-0 ${isCurrentProject ? 'bg-primary/5' : 'hover:bg-hover/50'}">
                    <td class="px-4 py-3">
                      <div class="flex items-center gap-2 min-w-0">
                        <span class="shrink-0">${isCurrentProject ? '<i data-lucide="map-pin" class="w-4 h-4 text-primary"></i>' : '<i data-lucide="folder" class="w-4 h-4"></i>'}</span>
                        <div class="min-w-0">
                          <div class="font-medium text-foreground truncate text-sm flex items-center gap-2" title="${escapeHtml(path)}">
                            <span class="truncate">${escapeHtml(path.split('\\').pop() || path)}</span>
                            ${isCurrentProject ? `<span class="text-xs text-primary font-medium shrink-0">${t('mcp.current')}</span>` : ''}
                            ${projectHasMcpJson ? `<span class="shrink-0 inline-flex items-center gap-1 px-1.5 py-0.5 text-xs bg-success/10 text-success rounded" title=".mcp.json detected"><i data-lucide="file-check" class="w-3 h-3"></i></span>` : ''}
                          </div>
                          <div class="text-xs text-muted-foreground truncate">${escapeHtml(path)}</div>
                        </div>
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="flex flex-wrap gap-1.5">
                        ${serverNames.length === 0
                          ? `<span class="text-xs text-muted-foreground italic">${t('mcp.noMcpServers')}</span>`
                          : serverNames.map(serverName => {
                              const isEnabled = !projectDisabled.includes(serverName);
                              return `
                                <span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium rounded-full ${isEnabled ? 'bg-success-light text-success' : 'bg-hover text-muted-foreground'}">
                                  <span class="w-1.5 h-1.5 rounded-full ${isEnabled ? 'bg-success' : 'bg-muted-foreground'}"></span>
                                  ${escapeHtml(serverName)}
                                </span>
                              `;
                            }).join('')
                        }
                      </div>
                    </td>
                    <td class="px-4 py-3 text-center">
                      <span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full ${serverNames.length > 0 ? 'bg-success-light text-success' : 'bg-hover text-muted-foreground'}">
                        ${enabledCount}/${serverNames.length}
                      </span>
                    </td>
                  </tr>
                `;
              }).join('')}
            </tbody>
          </table>
        </div>
      </div>
      ` : ''}
      `}

      <!-- MCP Server Details Modal -->
      <div id="mcpDetailsModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
        <div class="bg-card border border-border rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-hidden flex flex-col">
          <!-- Modal Header -->
          <div class="flex items-center justify-between px-6 py-4 border-b border-border">
            <h2 class="text-lg font-semibold text-foreground">${t('mcp.detailsModal.title')}</h2>
            <button id="mcpDetailsModalClose" class="text-muted-foreground hover:text-foreground transition-colors">
              <i data-lucide="x" class="w-5 h-5"></i>
            </button>
          </div>

          <!-- Modal Body -->
          <div id="mcpDetailsModalBody" class="px-6 py-4 overflow-y-auto flex-1">
            <!-- Content will be dynamically filled -->
          </div>
        </div>
      </div>
    </div>
  `;

  // Initialize Lucide icons FIRST (before attaching event listeners)
  // lucide.createIcons() may replace DOM elements, which would remove event listeners
  if (typeof lucide !== 'undefined') lucide.createIcons();
  
  // Attach event listeners AFTER icon initialization
  attachMcpEventListeners();
}

// Render card for Project Available MCP (current project can use)
function renderProjectAvailableServerCard(entry) {
  const { name, config, source, canRemove, canToggle, isEnabled } = entry;
  const command = config.command || 'N/A';
  const args = config.args || [];
  const hasEnv = config.env && Object.keys(config.env).length > 0;

  // Source badge
  let sourceBadge = '';
  if (source === 'enterprise') {
    sourceBadge = `<span class="text-xs px-2 py-0.5 bg-warning/20 text-warning rounded-full">${t('mcp.sourceEnterprise')}</span>`;
  } else if (source === 'global') {
    sourceBadge = `<span class="text-xs px-2 py-0.5 bg-success/10 text-success rounded-full">${t('mcp.sourceGlobal')}</span>`;
  } else if (source === 'project') {
    sourceBadge = `<span class="text-xs px-2 py-0.5 bg-primary/10 text-primary rounded-full">${t('mcp.sourceProject')}</span>`;
  }

  return `
    <div class="mcp-server-card bg-card border border-border rounded-lg p-4 hover:shadow-md transition-all cursor-pointer ${canToggle && !isEnabled ? 'opacity-60' : ''}"
         data-server-name="${escapeHtml(name)}"
         data-server-config="${encodeConfigData(config)}"
         data-server-source="${source}"
         data-action="view-details"
         title="${t('mcp.clickToViewDetails')}">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-center gap-2">
          <span>${canToggle && isEnabled ? '<i data-lucide="check-circle" class="w-5 h-5 text-success"></i>' : '<i data-lucide="circle" class="w-5 h-5 text-muted-foreground"></i>'}</span>
          <h4 class="font-semibold text-foreground">${escapeHtml(name)}</h4>
          ${sourceBadge}
        </div>
        ${canToggle ? `
          <label class="mcp-toggle relative inline-flex items-center cursor-pointer" onclick="event.stopPropagation()">
            <input type="checkbox" class="sr-only peer"
                   ${isEnabled ? 'checked' : ''}
                   data-server-name="${escapeHtml(name)}"
                   data-action="toggle">
            <div class="w-9 h-5 bg-hover peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-success"></div>
          </label>
        ` : ''}
      </div>

      <div class="mcp-server-details text-sm space-y-1">
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.cmd')}</span>
          <span class="truncate" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
        </div>
        ${args.length > 0 ? `
          <div class="flex items-start gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
            <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(args.slice(0, 3).join(' '))}${args.length > 3 ? '...' : ''}</span>
          </div>
        ` : ''}
        ${hasEnv ? `
          <div class="flex items-center gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.env')}</span>
            <span class="text-xs">${Object.keys(config.env).length} ${t('mcp.variables')}</span>
          </div>
        ` : ''}
      </div>

      <div class="mt-3 pt-3 border-t border-border flex items-center justify-between gap-2">
        <div class="flex items-center gap-2">
          <button class="text-xs text-success hover:text-success/80 transition-colors flex items-center gap-1"
                  data-server-name="${escapeHtml(name)}"
                  data-server-config="${encodeConfigData(config)}"
                  data-action="save-as-template"
                  onclick="event.stopPropagation()"
                  title="${t('mcp.saveAsTemplate')}">
            <i data-lucide="save" class="w-3 h-3"></i>
            ${t('mcp.saveAsTemplate')}
          </button>
        </div>
        ${canRemove ? `
          <button class="text-xs text-destructive hover:text-destructive/80 transition-colors"
                  data-server-name="${escapeHtml(name)}"
                  data-action="remove"
                  onclick="event.stopPropagation()">
            ${t('mcp.removeFromProject')}
          </button>
        ` : ''}
      </div>
    </div>
  `;
}

// Render card for Global Management (manage global servers)
function renderGlobalManagementCard(serverName, serverConfig) {
  const command = serverConfig.command || serverConfig.url || 'N/A';
  const args = serverConfig.args || [];
  const hasEnv = serverConfig.env && Object.keys(serverConfig.env).length > 0;
  const serverType = serverConfig.type || 'stdio';

  return `
    <div class="mcp-server-card mcp-server-global bg-card border border-success/30 rounded-lg p-4 hover:shadow-md transition-all cursor-pointer"
         data-server-name="${escapeHtml(serverName)}"
         data-server-config="${encodeConfigData(serverConfig)}"
         data-server-source="global"
         data-action="view-details"
         title="${t('mcp.clickToEdit')}">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-center gap-2">
          <i data-lucide="globe" class="w-5 h-5 text-success"></i>
          <h4 class="font-semibold text-foreground">${escapeHtml(serverName)}</h4>
        </div>
      </div>

      <div class="mcp-server-details text-sm space-y-1">
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${serverType === 'stdio' ? t('mcp.cmd') : t('mcp.url')}</span>
          <span class="truncate" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
        </div>
        ${args.length > 0 ? `
          <div class="flex items-start gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
            <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(args.slice(0, 3).join(' '))}${args.length > 3 ? '...' : ''}</span>
          </div>
        ` : ''}
        ${hasEnv ? `
          <div class="flex items-center gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.env')}</span>
            <span class="text-xs">${Object.keys(serverConfig.env).length} ${t('mcp.variables')}</span>
          </div>
        ` : ''}
        <div class="flex items-center gap-2 text-muted-foreground mt-1">
          <span class="text-xs italic">${t('mcp.availableToAll')}</span>
        </div>
      </div>

      <div class="mt-3 pt-3 border-t border-border flex items-center justify-end">
        <button class="text-xs text-destructive hover:text-destructive/80 transition-colors"
                data-server-name="${escapeHtml(serverName)}"
                data-action="remove-global"
                onclick="event.stopPropagation()">
          ${t('mcp.removeGlobal')}
        </button>
      </div>
    </div>
  `;
}

function renderAvailableServerCard(serverName, serverInfo) {
  const serverConfig = serverInfo.config;
  const usedIn = serverInfo.usedIn || [];
  const command = serverConfig.command || 'N/A';
  const args = serverConfig.args || [];

  // Get the actual name to use when adding (original name if different from display key)
  const originalName = serverInfo.originalName || serverName;
  const hasVariant = serverInfo.originalName && serverInfo.originalName !== serverName;

  // Get source project info
  const sourceProject = serverInfo.sourceProject;
  const sourceProjectName = sourceProject ? (sourceProject.split('\\').pop() || sourceProject.split('/').pop()) : null;

  // Generate args preview
  const argsPreview = args.length > 0 ? args.slice(0, 3).join(' ') + (args.length > 3 ? '...' : '') : '';

  return `
    <div class="mcp-server-card mcp-server-available bg-card border border-border border-dashed rounded-lg p-4 hover:shadow-md hover:border-solid transition-all">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-center gap-2 flex-wrap">
          <span><i data-lucide="circle-dashed" class="w-5 h-5 text-muted-foreground"></i></span>
          <h4 class="font-semibold text-foreground">${escapeHtml(originalName)}</h4>
          ${hasVariant ? `
            <span class="text-xs px-2 py-0.5 bg-warning/20 text-warning rounded-full" title="Different config from: ${escapeHtml(sourceProject || '')}">
              ${escapeHtml(sourceProjectName || 'variant')}
            </span>
          ` : ''}
        </div>
        <div class="flex gap-2">
          <button class="px-3 py-1 text-xs bg-primary text-primary-foreground rounded hover:opacity-90 transition-opacity"
                  data-server-name="${escapeHtml(originalName)}"
                  data-server-key="${escapeHtml(serverName)}"
                  data-server-config="${encodeConfigData(serverConfig)}"
                  data-scope="project"
                  data-action="add-from-other"
                  title="${t('mcp.installToProject')}">
            <i data-lucide="folder-plus" class="w-3.5 h-3.5 inline"></i>
          </button>
          <button class="px-3 py-1 text-xs bg-success text-success-foreground rounded hover:opacity-90 transition-opacity"
                  data-server-name="${escapeHtml(originalName)}"
                  data-server-key="${escapeHtml(serverName)}"
                  data-server-config="${encodeConfigData(serverConfig)}"
                  data-scope="global"
                  data-action="add-from-other"
                  title="${t('mcp.installToGlobal')}">
            <i data-lucide="globe" class="w-3.5 h-3.5 inline"></i>
          </button>
        </div>
      </div>

      <div class="mcp-server-details text-sm space-y-1">
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.cmd')}</span>
          <span class="truncate" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
        </div>
        ${argsPreview ? `
          <div class="flex items-start gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
            <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(argsPreview)}</span>
          </div>
        ` : ''}
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="text-xs">${t('mcp.usedInCount').replace('{count}', usedIn.length).replace('{s}', usedIn.length !== 1 ? 's' : '')}</span>
          ${sourceProjectName ? `<span class="text-xs text-muted-foreground/70">• ${t('mcp.from')} ${escapeHtml(sourceProjectName)}</span>` : ''}
        </div>
      </div>

      <div class="mt-3 pt-3 border-t border-border flex items-center gap-2">
        <button class="text-xs text-primary hover:text-primary/80 transition-colors flex items-center gap-1"
                data-server-name="${escapeHtml(originalName)}"
                data-server-config="${encodeConfigData(serverConfig)}"
                data-action="install-to-project"
                title="${t('mcp.installToProject')}">
          <i data-lucide="download" class="w-3 h-3"></i>
          ${t('mcp.installToProject')}
        </button>
        <button class="text-xs text-success hover:text-success/80 transition-colors flex items-center gap-1"
                data-server-name="${escapeHtml(originalName)}"
                data-server-config="${encodeConfigData(serverConfig)}"
                data-action="install-to-global"
                title="${t('mcp.installToGlobal')}">
          <i data-lucide="globe" class="w-3 h-3"></i>
          ${t('mcp.installToGlobal')}
        </button>
      </div>
    </div>
  `;
}

// Render available server card for Codex mode (with Claude badge and copy to Codex button)
function renderAvailableServerCardForCodex(serverName, serverInfo) {
  const serverConfig = serverInfo.config;
  const usedIn = serverInfo.usedIn || [];
  const command = serverConfig.command || serverConfig.url || 'N/A';
  const args = serverConfig.args || [];

  // Get the actual name to use when adding
  const originalName = serverInfo.originalName || serverName;
  const hasVariant = serverInfo.originalName && serverInfo.originalName !== serverName;

  // Get source project info
  const sourceProject = serverInfo.sourceProject;
  const sourceProjectName = sourceProject ? (sourceProject.split('\\').pop() || sourceProject.split('/').pop()) : null;

  // Generate args preview
  const argsPreview = args.length > 0 ? args.slice(0, 3).join(' ') + (args.length > 3 ? '...' : '') : '';

  // Check if already in Codex
  const alreadyInCodex = codexMcpServers && codexMcpServers[originalName];

  return `
    <div class="mcp-server-card mcp-server-available bg-card border ${alreadyInCodex ? 'border-success/50' : 'border-border'} border-dashed rounded-lg p-4 hover:shadow-md hover:border-solid transition-all">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-center gap-2 flex-wrap">
          <span><i data-lucide="circle-dashed" class="w-5 h-5 text-muted-foreground"></i></span>
          <h4 class="font-semibold text-foreground">${escapeHtml(originalName)}</h4>
          <span class="text-xs px-2 py-0.5 bg-primary/10 text-primary rounded-full">Claude</span>
          ${hasVariant ? `
            <span class="text-xs px-2 py-0.5 bg-warning/20 text-warning rounded-full" title="Different config from: ${escapeHtml(sourceProject || '')}">
              ${escapeHtml(sourceProjectName || 'variant')}
            </span>
          ` : ''}
          ${alreadyInCodex ? `<span class="text-xs px-2 py-0.5 bg-success/10 text-success rounded-full">${t('mcp.codex.alreadyAdded')}</span>` : ''}
        </div>
        ${!alreadyInCodex ? `
          <button class="px-3 py-1 text-xs bg-primary text-primary-foreground rounded hover:opacity-90 transition-opacity"
                  data-action="copy-to-codex"
                  data-server-name="${escapeHtml(originalName)}"
                  data-server-config="${encodeConfigData(serverConfig)}"
                  title="${t('mcp.codex.copyToCodex')}">
            <i data-lucide="arrow-right" class="w-3.5 h-3.5 inline"></i> Codex
          </button>
        ` : ''}
      </div>

      <div class="mcp-server-details text-sm space-y-1">
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.cmd')}</span>
          <span class="truncate" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
        </div>
        ${argsPreview ? `
          <div class="flex items-start gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
            <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(argsPreview)}</span>
          </div>
        ` : ''}
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="text-xs">${t('mcp.usedInCount').replace('{count}', usedIn.length).replace('{s}', usedIn.length !== 1 ? 's' : '')}</span>
          ${sourceProjectName ? `<span class="text-xs text-muted-foreground/70">• ${t('mcp.from')} ${escapeHtml(sourceProjectName)}</span>` : ''}
        </div>
      </div>

      <div class="mt-3 pt-3 border-t border-border flex items-center gap-2">
        <button class="text-xs text-primary hover:text-primary/80 transition-colors flex items-center gap-1"
                data-action="copy-to-codex"
                data-server-name="${escapeHtml(originalName)}"
                data-server-config="${encodeConfigData(serverConfig)}"
                title="${t('mcp.codex.copyToCodex')}">
          <i data-lucide="download" class="w-3 h-3"></i>
          ${t('mcp.codex.install')}
        </button>
      </div>
    </div>
  `;
}

// ========================================
// Codex MCP Server Card Renderer
// ========================================

function renderCodexServerCard(serverName, serverConfig) {
  const isStdio = !!serverConfig.command;
  const isHttp = !!serverConfig.url;
  const isEnabled = serverConfig.enabled !== false; // Default to enabled
  const command = serverConfig.command || serverConfig.url || 'N/A';
  const args = serverConfig.args || [];
  const hasEnv = serverConfig.env && Object.keys(serverConfig.env).length > 0;

  // Server type badge
  const typeBadge = isHttp
    ? `<span class="text-xs px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300 rounded-full">HTTP</span>`
    : `<span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">STDIO</span>`;

  return `
    <div class="mcp-server-card bg-card border border-primary/20 rounded-lg p-4 hover:shadow-md transition-all cursor-pointer ${!isEnabled ? 'opacity-60' : ''}"
         data-server-name="${escapeHtml(serverName)}"
         data-server-config="${encodeConfigData(serverConfig)}"
         data-cli-type="codex"
         data-action="view-details-codex"
         title="${t('mcp.clickToEdit')}">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-center gap-2 flex-wrap">
          <span>${isEnabled ? '<i data-lucide="check-circle" class="w-5 h-5 text-primary"></i>' : '<i data-lucide="circle" class="w-5 h-5 text-muted-foreground"></i>'}</span>
          <h4 class="font-semibold text-foreground">${escapeHtml(serverName)}</h4>
          <span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">Codex</span>
          ${typeBadge}
        </div>
        <label class="mcp-toggle relative inline-flex items-center cursor-pointer" onclick="event.stopPropagation()">
          <input type="checkbox" class="sr-only peer"
                 ${isEnabled ? 'checked' : ''}
                 data-server-name="${escapeHtml(serverName)}"
                 data-action="toggle-codex">
          <div class="w-9 h-5 bg-hover peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-primary"></div>
        </label>
      </div>

      <div class="mcp-server-details text-sm space-y-1">
        <div class="flex items-center gap-2 text-muted-foreground">
          <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${isHttp ? t('mcp.url') : t('mcp.cmd')}</span>
          <span class="truncate" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
        </div>
        ${args.length > 0 ? `
          <div class="flex items-start gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
            <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(args.slice(0, 3).join(' '))}${args.length > 3 ? '...' : ''}</span>
          </div>
        ` : ''}
        ${hasEnv ? `
          <div class="flex items-center gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.env')}</span>
            <span class="text-xs">${Object.keys(serverConfig.env).length} ${t('mcp.variables')}</span>
          </div>
        ` : ''}
        ${serverConfig.enabled_tools ? `
          <div class="flex items-center gap-2 text-muted-foreground">
            <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${t('mcp.codex.enabledTools')}</span>
            <span class="text-xs">${serverConfig.enabled_tools.length} ${t('mcp.codex.tools')}</span>
          </div>
        ` : ''}
      </div>

      <div class="mt-3 pt-3 border-t border-border flex items-center justify-between gap-2" onclick="event.stopPropagation()">
        <div class="flex items-center gap-2">
          <button class="text-xs text-primary hover:text-primary/80 transition-colors flex items-center gap-1"
                  data-action="copy-codex-to-claude"
                  data-server-name="${escapeHtml(serverName)}"
                  data-server-config="${encodeConfigData(serverConfig)}"
                  title="${t('mcp.codex.copyToClaude')}">
            <i data-lucide="copy" class="w-3 h-3"></i>
            ${t('mcp.codex.copyToClaude')}
          </button>
        </div>
        <button class="text-xs text-destructive hover:text-destructive/80 transition-colors"
                data-server-name="${escapeHtml(serverName)}"
                data-action="remove-codex">
          ${t('mcp.codex.remove')}
        </button>
      </div>
    </div>
  `;
}

// Render card for cross-CLI servers (servers from other CLI not in current CLI)
function renderCrossCliServerCard(server, isClaude) {
  const { name, config, fromCli } = server;
  const isStdio = !!config.command;
  const isHttp = !!config.url;
  const command = config.command || config.url || 'N/A';
  const args = config.args || [];

  // Icon and color based on source CLI
  const icon = fromCli === 'codex' ? 'circle-dashed' : 'circle';
  const sourceBadgeColor = fromCli === 'codex' ? 'green' : 'orange';
  const targetCli = isClaude ? 'project' : 'codex';
  const buttonText = isClaude ? t('mcp.codex.copyToClaude') : t('mcp.claude.copyToCodex');
  const typeBadge = isHttp
    ? `<span class="text-xs px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300 rounded-full">HTTP</span>`
    : `<span class="text-xs px-2 py-0.5 bg-muted text-muted-foreground rounded-full">STDIO</span>`;

  // CLI badge with color
  const cliBadge = fromCli === 'codex'
    ? `<span class="text-xs px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded-full">Codex</span>`
    : `<span class="text-xs px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300 rounded-full">Claude</span>`;

  return `
    <div class="mcp-server-card bg-card border border-dashed border-primary/20 rounded-lg p-4 hover:shadow-md hover:border-solid transition-all">
      <div class="flex items-start justify-between mb-3">
        <div class="flex items-start gap-3">
          <div class="shrink-0">
            <i data-lucide="${icon}" class="w-5 h-5 text-primary"></i>
          </div>
          <div>
            <div class="flex items-center gap-2 flex-wrap mb-1">
              <h4 class="font-semibold text-foreground">${escapeHtml(name)}</h4>
              ${cliBadge}
              ${typeBadge}
            </div>
            <div class="text-sm space-y-1 text-muted-foreground">
              <div class="flex items-center gap-2">
                <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">${isHttp ? t('mcp.url') : t('mcp.cmd')}</span>
                <span class="truncate text-xs" title="${escapeHtml(command)}">${escapeHtml(command)}</span>
              </div>
              ${args.length > 0 ? `
                <div class="flex items-start gap-2">
                  <span class="font-mono text-xs bg-muted px-1.5 py-0.5 rounded shrink-0">${t('mcp.args')}</span>
                  <span class="text-xs font-mono truncate" title="${escapeHtml(args.join(' '))}">${escapeHtml(args.slice(0, 3).join(' '))}${args.length > 3 ? '...' : ''}</span>
                </div>
              ` : ''}
            </div>
          </div>
        </div>
      </div>
      <div class="mt-3 pt-3 border-t border-border">
        <button class="w-full px-3 py-2 text-sm font-medium bg-primary hover:bg-primary/90 text-primary-foreground rounded-lg transition-colors flex items-center justify-center gap-1.5"
                data-action="copy-cross-cli"
                data-server-name="${escapeHtml(name)}"
                data-server-config="${encodeConfigData(config)}"
                data-from-cli="${fromCli}"
                data-target-cli="${targetCli}">
          <i data-lucide="copy" class="w-4 h-4"></i>
          ${buttonText}
        </button>
      </div>
    </div>
  `;
}

// Copy server from one CLI to another
async function copyCrossCliServer(name, config, fromCli, targetCli) {
  try {
    let endpoint, body;

    if (targetCli === 'codex') {
      // Copy from Claude to Codex
      endpoint = '/api/codex-mcp-add';
      body = { serverName: name, serverConfig: config };
    } else if (targetCli === 'project') {
      // Copy from Codex to Claude project
      endpoint = '/api/mcp-copy-server';
      body = { projectPath, serverName: name, serverConfig: config, configType: 'mcp' };
    } else if (targetCli === 'global') {
      // Copy to Claude global
      endpoint = '/api/mcp-add-global-server';
      body = { serverName: name, serverConfig: config };
    }

    const res = await fetch(endpoint, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body)
    });

    const data = await res.json();
    if (data.success) {
      const targetName = targetCli === 'codex' ? 'Codex' : 'Claude';
      showToast(t('mcp.success'), `${t('mcp.serverInstalled')} (${targetName})`, 'success');
      await loadMcpConfig();
      renderMcpManager();
    } else {
      showToast(t('mcp.error'), data.error, 'error');
    }
  } catch (error) {
    showToast(t('mcp.error'), error.message, 'error');
  }
}

// ========================================
// Codex MCP Create Modal
// ========================================

function openCodexMcpCreateModal() {
  // Reuse the existing modal with different settings
  const modal = document.getElementById('mcpCreateModal');
  if (modal) {
    modal.classList.remove('hidden');
    // Reset to form mode
    mcpCreateMode = 'form';
    switchMcpCreateTab('form');
    // Clear form
    document.getElementById('mcpServerName').value = '';
    document.getElementById('mcpServerCommand').value = '';
    document.getElementById('mcpServerArgs').value = '';
    document.getElementById('mcpServerEnv').value = '';
    // Clear JSON input
    document.getElementById('mcpServerJson').value = '';
    document.getElementById('mcpJsonPreview').classList.add('hidden');
    // Set scope to codex
    const scopeSelect = document.getElementById('mcpServerScope');
    if (scopeSelect) {
      // Add codex option if not exists
      if (!scopeSelect.querySelector('option[value="codex"]')) {
        const codexOption = document.createElement('option');
        codexOption.value = 'codex';
        codexOption.textContent = t('mcp.codex.scopeCodex');
        scopeSelect.appendChild(codexOption);
      }
      scopeSelect.value = 'codex';
    }
    // Focus on name input
    document.getElementById('mcpServerName').focus();
    // Setup JSON input listener
    setupMcpJsonListener();
  }
}

function attachMcpEventListeners() {
  // Debug: Log event listener attachment
  const viewDetailsCards = document.querySelectorAll('.mcp-server-card[data-action="view-details"]');
  const codexCards = document.querySelectorAll('.mcp-server-card[data-action="view-details-codex"]');
  console.log('[MCP] Attaching event listeners - Claude cards:', viewDetailsCards.length, 'Codex cards:', codexCards.length);

  // Toggle switches
  document.querySelectorAll('.mcp-server-card input[data-action="toggle"]').forEach(input => {
    input.addEventListener('change', async (e) => {
      const serverName = e.target.dataset.serverName;
      const enable = e.target.checked;
      await toggleMcpServer(serverName, enable);
    });
  });

  // Add from other projects (with scope selection)
  document.querySelectorAll('.mcp-server-card button[data-action="add-from-other"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      try {
        const serverName = btn.dataset.serverName;
        const serverConfig = decodeConfigData(btn.dataset.serverConfig);
        const scope = btn.dataset.scope; // 'project' or 'global'

        if (scope === 'global') {
          await addGlobalMcpServer(serverName, serverConfig);
        } else {
          await copyMcpServerToProject(serverName, serverConfig);
        }
      } catch (err) {
        console.error('[MCP] Error adding server from other project:', err);
      }
    });
  });

  // Remove buttons (project-level)
  document.querySelectorAll('.mcp-server-card button[data-action="remove"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      const serverName = btn.dataset.serverName;
      if (confirm(t('mcp.removeConfirm', { name: serverName }))) {
        await removeMcpServerFromProject(serverName);
      }
    });
  });

  // Remove buttons (global-level)
  document.querySelectorAll('.mcp-server-card button[data-action="remove-global"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      const serverName = btn.dataset.serverName;
      if (confirm(t('mcp.removeGlobalConfirm', { name: serverName }))) {
        await removeGlobalMcpServer(serverName);
      }
    });
  });

  // Install to project buttons
  document.querySelectorAll('.mcp-server-card button[data-action="install-to-project"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      try {
        const serverName = btn.dataset.serverName;
        const serverConfig = decodeConfigData(btn.dataset.serverConfig);
        await copyMcpServerToProject(serverName, serverConfig);
      } catch (err) {
        console.error('[MCP] Error installing to project:', err);
      }
    });
  });

  // Install to global buttons
  document.querySelectorAll('.mcp-server-card button[data-action="install-to-global"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      try {
        const serverName = btn.dataset.serverName;
        const serverConfig = decodeConfigData(btn.dataset.serverConfig);
        await addGlobalMcpServer(serverName, serverConfig);
      } catch (err) {
        console.error('[MCP] Error installing to global:', err);
      }
    });
  });

  // Save as template buttons
  document.querySelectorAll('.mcp-server-card button[data-action="save-as-template"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      try {
        const serverName = btn.dataset.serverName;
        const serverConfig = decodeConfigData(btn.dataset.serverConfig);
        await saveMcpAsTemplate(serverName, serverConfig);
      } catch (err) {
        console.error('[MCP] Error saving as template:', err);
      }
    });
  });

  // Install from template buttons
  document.querySelectorAll('.mcp-template-card button[data-action="install-template"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      const templateName = btn.dataset.templateName;
      const scope = btn.dataset.scope || 'project';
      await installFromTemplate(templateName, scope);
    });
  });

  // Delete template buttons
  document.querySelectorAll('.mcp-template-card button[data-action="delete-template"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      const templateName = btn.dataset.templateName;
      if (confirm(t('mcp.deleteTemplateConfirm', { name: templateName }))) {
        await deleteMcpTemplate(templateName);
      }
    });
  });

  // ========================================
  // CCW Tools MCP Event Listeners
  // ========================================

  // CCW Tools action buttons (workspace/global install/update)
  const ccwActions = {
    'update-ccw-workspace': () => updateCcwToolsMcp('workspace'),
    'update-ccw-global': () => updateCcwToolsMcp('global'),
    'install-ccw-workspace': () => installCcwToolsMcp('workspace'),
    'install-ccw-global': () => installCcwToolsMcp('global'),
    'install-ccw-codex': () => installCcwToolsMcpToCodex()
  };

  // Mode-specific and conditionally rendered actions (don't warn if not found)
  const conditionalActions = new Set([
    'install-ccw-codex',      // Only in Codex mode
    'update-ccw-workspace',   // Only if ccw-tools installed
    'update-ccw-global'       // Only if ccw-tools installed
  ]);

  Object.entries(ccwActions).forEach(([action, handler]) => {
    const btns = document.querySelectorAll(`button[data-action="${action}"]`);

    if (btns.length > 0) {
      console.log(`[MCP] Attaching listener to ${action} (${btns.length} button(s) found)`);
      btns.forEach(btn => {
        btn.addEventListener('click', async (e) => {
          e.preventDefault();
          console.log(`[MCP] Button clicked: ${action}`);
          try {
            await handler();
          } catch (err) {
            console.error(`[MCP] Error executing handler for ${action}:`, err);
            if (typeof showRefreshToast === 'function') {
              showRefreshToast(`Action failed: ${err.message}`, 'error');
            }
          }
        });
      });
    } else if (!conditionalActions.has(action)) {
      // Only warn if button is not conditionally rendered
      console.warn(`[MCP] No buttons found for action: ${action}`);
    }
  });

  // ========================================
  // Codex MCP Event Listeners
  // ========================================

  // Toggle Codex MCP servers
  document.querySelectorAll('.mcp-server-card input[data-action="toggle-codex"]').forEach(input => {
    input.addEventListener('change', async (e) => {
      const serverName = e.target.dataset.serverName;
      const enable = e.target.checked;
      await toggleCodexMcpServer(serverName, enable);
    });
  });

  // Remove Codex MCP servers
  document.querySelectorAll('.mcp-server-card button[data-action="remove-codex"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      const serverName = btn.dataset.serverName;
      if (confirm(t('mcp.codex.removeConfirm', { name: serverName }))) {
        await removeCodexMcpServer(serverName);
      }
    });
  });

  // Copy Claude servers to Codex
  document.querySelectorAll('button[data-action="copy-to-codex"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      e.preventDefault();
      try {
        const serverName = btn.dataset.serverName;
        const serverConfig = decodeConfigData(btn.dataset.serverConfig);
        console.log('[MCP] Copying to Codex:', serverName);
        await copyClaudeServerToCodex(serverName, serverConfig);
      } catch (err) {
        console.error('[MCP] Error copying to Codex:', err);
      }
    });
  });

  // Copy Codex servers to Claude
  document.querySelectorAll('button[data-action="copy-codex-to-claude"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      e.preventDefault();
      e.stopPropagation();
      const serverName = btn.dataset.serverName;
      let serverConfig;
      try {
        serverConfig = decodeConfigData(btn.dataset.serverConfig);
      } catch (err) {
        console.error('[MCP] JSON Parse Error:', err);
        if (typeof showRefreshToast === 'function') {
          showRefreshToast('Failed to parse server configuration', 'error');
        }
        return;
      }
      console.log('[MCP] Copying Codex to Claude:', serverName);
      await copyCodexServerToClaude(serverName, serverConfig);
    });
  });

  // Copy servers across CLI tools
  document.querySelectorAll('button[data-action="copy-cross-cli"]').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      e.preventDefault();
      e.stopPropagation();
      const serverName = btn.dataset.serverName;
      let serverConfig;
      try {
        serverConfig = decodeConfigData(btn.dataset.serverConfig);
      } catch (err) {
        console.error('[MCP] JSON Parse Error:', err);
        if (typeof showRefreshToast === 'function') {
          showRefreshToast('Failed to parse server configuration', 'error');
        }
        return;
      }
      const fromCli = btn.dataset.fromCli;
      const targetCli = btn.dataset.targetCli;
      console.log('[MCP] Copying cross-CLI:', serverName, 'from', fromCli, 'to', targetCli);
      await copyCrossCliServer(serverName, serverConfig, fromCli, targetCli);
    });
  });

  // View details / Edit - click on Claude server card
  document.querySelectorAll('.mcp-server-card[data-action="view-details"]').forEach(card => {
    card.addEventListener('click', (e) => {
      // Don't trigger if clicking on buttons or toggle
      if (e.target.closest('button') || e.target.closest('label') || e.target.closest('input')) {
        return;
      }
      try {
        const serverName = card.dataset.serverName;
        const configData = card.dataset.serverConfig;
        if (!configData) {
          console.error('[MCP] Missing server config for:', serverName);
          return;
        }
        const serverConfig = decodeConfigData(configData);
        if (!serverConfig) {
          console.error('[MCP] Failed to decode server config for:', serverName);
          return;
        }
        const serverSource = card.dataset.serverSource;
        console.log('[MCP] Card clicked:', serverName, serverSource);
        showMcpEditModal(serverName, serverConfig, serverSource, 'claude');
      } catch (err) {
        console.error('[MCP] Error handling card click:', err);
      }
    });
  });

  // View details / Edit - click on Codex server card
  document.querySelectorAll('.mcp-server-card[data-action="view-details-codex"]').forEach(card => {
    card.addEventListener('click', (e) => {
      // Don't trigger if clicking on buttons or toggle
      if (e.target.closest('button') || e.target.closest('label') || e.target.closest('input')) {
        return;
      }
      try {
        const serverName = card.dataset.serverName;
        const configData = card.dataset.serverConfig;
        if (!configData) {
          console.error('[MCP] Missing server config for:', serverName);
          return;
        }
        const serverConfig = decodeConfigData(configData);
        if (!serverConfig) {
          console.error('[MCP] Failed to decode server config for:', serverName);
          return;
        }
        console.log('[MCP] Codex card clicked:', serverName);
        showMcpEditModal(serverName, serverConfig, 'codex', 'codex');
      } catch (err) {
        console.error('[MCP] Error handling Codex card click:', err);
      }
    });
  });

  // Modal close button
  const closeBtn = document.getElementById('mcpDetailsModalClose');
  const modal = document.getElementById('mcpDetailsModal');
  if (closeBtn && modal) {
    closeBtn.addEventListener('click', () => {
      modal.classList.add('hidden');
    });
    // Close on background click
    modal.addEventListener('click', (e) => {
      if (e.target === modal) {
        modal.classList.add('hidden');
      }
    });
  }
}

// ========================================
// MCP Edit Modal (replaces Details Modal)
// ========================================

// Store current editing context
let mcpEditContext = {
  serverName: null,
  serverConfig: null,
  serverSource: null,
  cliType: 'claude'
};

function showMcpDetails(serverName, serverConfig, serverSource, cliType = 'claude') {
  showMcpEditModal(serverName, serverConfig, serverSource, cliType);
}

function showMcpEditModal(serverName, serverConfig, serverSource, cliType = 'claude') {
  const modal = document.getElementById('mcpDetailsModal');
  const modalBody = document.getElementById('mcpDetailsModalBody');

  if (!modal || !modalBody) return;

  // Store editing context
  mcpEditContext = {
    serverName,
    serverConfig: JSON.parse(JSON.stringify(serverConfig)), // Deep clone
    serverSource,
    cliType
  };

  // Check if editable (enterprise is read-only)
  const isReadOnly = serverSource === 'enterprise';
  const isCodex = cliType === 'codex';

  // Build source badge
  let sourceBadge = '';
  if (serverSource === 'enterprise') {
    sourceBadge = `<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full bg-warning/20 text-warning">${t('mcp.sourceEnterprise')}</span>`;
  } else if (serverSource === 'global') {
    sourceBadge = `<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full bg-success/10 text-success">${t('mcp.sourceGlobal')}</span>`;
  } else if (serverSource === 'project') {
    sourceBadge = `<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full bg-primary/10 text-primary">${t('mcp.sourceProject')}</span>`;
  } else if (isCodex) {
    sourceBadge = `<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300">Codex</span>`;
  }

  // Format args and env for textarea
  const argsText = (serverConfig.args || []).join('\n');
  const envText = Object.entries(serverConfig.env || {}).map(([k, v]) => `${k}=${v}`).join('\n');

  // Build edit form HTML
  modalBody.innerHTML = `
    <div class="space-y-4">
      <!-- Server Name and Source -->
      <div>
        <label class="text-xs font-semibold text-muted-foreground uppercase tracking-wide">${t('mcp.detailsModal.serverName')}</label>
        <div class="mt-1 flex items-center gap-2">
          <input type="text" id="mcpEditName" value="${escapeHtml(serverName)}"
                 class="text-lg font-bold text-foreground bg-transparent border-b border-border focus:border-primary outline-none px-1 py-0.5 flex-1"
                 ${isReadOnly ? 'disabled' : ''}
                 placeholder="${t('mcp.editModal.serverNamePlaceholder')}">
          ${sourceBadge}
        </div>
      </div>

      <!-- Command/URL -->
      <div>
        <label class="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1 block">
          ${serverConfig.url ? t('mcp.url') : t('mcp.cmd')}
        </label>
        <input type="text" id="mcpEditCommand" value="${escapeHtml(serverConfig.command || serverConfig.url || '')}"
               class="w-full px-3 py-2 text-sm font-mono bg-muted border border-border rounded-lg focus:border-primary outline-none"
               ${isReadOnly ? 'disabled' : ''}
               placeholder="${serverConfig.url ? 'https://...' : 'npx, node, python...'}">
      </div>

      <!-- Arguments -->
      <div>
        <label class="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1 block">
          ${t('mcp.args')} <span class="font-normal">(${t('mcp.editModal.onePerLine')})</span>
        </label>
        <textarea id="mcpEditArgs" rows="3"
                  class="w-full px-3 py-2 text-sm font-mono bg-muted border border-border rounded-lg focus:border-primary outline-none resize-none"
                  ${isReadOnly ? 'disabled' : ''}
                  placeholder="-y&#10;package-name">${escapeHtml(argsText)}</textarea>
      </div>

      <!-- Environment Variables -->
      <div>
        <label class="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1 block">
          ${t('mcp.env')} <span class="font-normal">(KEY=VALUE ${t('mcp.editModal.onePerLine')})</span>
        </label>
        <textarea id="mcpEditEnv" rows="3"
                  class="w-full px-3 py-2 text-sm font-mono bg-muted border border-border rounded-lg focus:border-primary outline-none resize-none"
                  ${isReadOnly ? 'disabled' : ''}
                  placeholder="API_KEY=your-key&#10;DEBUG=true">${escapeHtml(envText)}</textarea>
      </div>

      ${isCodex ? `
      <!-- Codex-specific: enabled_tools -->
      <div>
        <label class="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1 block">
          ${t('mcp.codex.enabledTools')} <span class="font-normal">(${t('mcp.editModal.onePerLine')})</span>
        </label>
        <textarea id="mcpEditEnabledTools" rows="2"
                  class="w-full px-3 py-2 text-sm font-mono bg-muted border border-border rounded-lg focus:border-primary outline-none resize-none"
                  ${isReadOnly ? 'disabled' : ''}
                  placeholder="tool1&#10;tool2">${escapeHtml((serverConfig.enabled_tools || []).join('\n'))}</textarea>
      </div>
      ` : ''}

      <!-- Raw JSON Preview (collapsible) -->
      <details class="group">
        <summary class="text-xs font-semibold text-muted-foreground uppercase tracking-wide cursor-pointer flex items-center gap-1">
          <i data-lucide="chevron-right" class="w-3 h-3 transition-transform group-open:rotate-90"></i>
          Raw JSON
        </summary>
        <pre id="mcpEditJsonPreview" class="mt-2 bg-muted rounded-lg p-3 text-xs font-mono overflow-x-auto">${escapeHtml(JSON.stringify(serverConfig, null, 2))}</pre>
      </details>

      <!-- Action Buttons -->
      ${!isReadOnly ? `
      <div class="flex items-center justify-between pt-4 border-t border-border">
        <div class="flex items-center gap-2">
          ${serverSource === 'project' || isCodex ? `
            <button onclick="deleteMcpFromEdit()" class="px-4 py-2 text-sm text-destructive hover:bg-destructive/10 rounded-lg transition-colors flex items-center gap-1.5">
              <i data-lucide="trash-2" class="w-4 h-4"></i>
              ${t('mcp.editModal.delete')}
            </button>
          ` : ''}
        </div>
        <div class="flex items-center gap-2">
          <button onclick="closeMcpEditModal()" class="px-4 py-2 text-sm text-muted-foreground hover:bg-muted rounded-lg transition-colors">
            ${t('common.cancel')}
          </button>
          <button onclick="saveMcpEdit()" class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1.5">
            <i data-lucide="check" class="w-4 h-4"></i>
            ${t('mcp.editModal.save')}
          </button>
        </div>
      </div>
      ` : `
      <div class="flex items-center justify-end pt-4 border-t border-border">
        <button onclick="closeMcpEditModal()" class="px-4 py-2 text-sm bg-muted text-foreground rounded-lg hover:bg-muted/80 transition-colors">
          ${t('common.close')}
        </button>
      </div>
      `}
    </div>
  `;

  // Update modal title
  const modalTitle = modal.querySelector('h2');
  if (modalTitle) {
    modalTitle.textContent = isReadOnly ? t('mcp.detailsModal.title') : t('mcp.editModal.title');
  }

  // Show modal
  modal.classList.remove('hidden');

  // Re-initialize Lucide icons in modal
  if (typeof lucide !== 'undefined') lucide.createIcons();

  // Add input listeners to update JSON preview
  if (!isReadOnly) {
    ['mcpEditCommand', 'mcpEditArgs', 'mcpEditEnv', 'mcpEditEnabledTools'].forEach(id => {
      const el = document.getElementById(id);
      if (el) {
        el.addEventListener('input', updateMcpEditJsonPreview);
      }
    });
  }
}

function closeMcpEditModal() {
  const modal = document.getElementById('mcpDetailsModal');
  if (modal) {
    modal.classList.add('hidden');
  }
  mcpEditContext = { serverName: null, serverConfig: null, serverSource: null, cliType: 'claude' };
}

function updateMcpEditJsonPreview() {
  const preview = document.getElementById('mcpEditJsonPreview');
  if (!preview) return;

  const config = buildConfigFromEditForm();
  preview.textContent = JSON.stringify(config, null, 2);
}

function buildConfigFromEditForm() {
  const command = document.getElementById('mcpEditCommand')?.value.trim() || '';
  const argsText = document.getElementById('mcpEditArgs')?.value.trim() || '';
  const envText = document.getElementById('mcpEditEnv')?.value.trim() || '';
  const enabledToolsEl = document.getElementById('mcpEditEnabledTools');

  // Build config
  const config = {};

  // Command or URL
  if (mcpEditContext.serverConfig?.url) {
    config.url = command;
  } else {
    config.command = command;
  }

  // Args
  if (argsText) {
    config.args = argsText.split('\n').map(a => a.trim()).filter(a => a);
  }

  // Env
  if (envText) {
    config.env = {};
    envText.split('\n').forEach(line => {
      const trimmed = line.trim();
      if (trimmed && trimmed.includes('=')) {
        const eqIndex = trimmed.indexOf('=');
        const key = trimmed.substring(0, eqIndex).trim();
        const value = trimmed.substring(eqIndex + 1).trim();
        if (key) {
          config.env[key] = value;
        }
      }
    });
  }

  // Codex-specific: enabled_tools
  if (enabledToolsEl) {
    const toolsText = enabledToolsEl.value.trim();
    if (toolsText) {
      config.enabled_tools = toolsText.split('\n').map(t => t.trim()).filter(t => t);
    }
  }

  return config;
}

async function saveMcpEdit() {
  const newName = document.getElementById('mcpEditName')?.value.trim();
  if (!newName) {
    showRefreshToast(t('mcp.editModal.nameRequired'), 'error');
    return;
  }

  const newConfig = buildConfigFromEditForm();

  if (!newConfig.command && !newConfig.url) {
    showRefreshToast(t('mcp.editModal.commandRequired'), 'error');
    return;
  }

  const { serverName, serverSource, cliType } = mcpEditContext;
  const nameChanged = newName !== serverName;

  try {
    if (cliType === 'codex') {
      // Codex MCP update
      // If name changed, remove old and add new
      if (nameChanged) {
        await removeCodexMcpServer(serverName);
      }
      await addCodexMcpServer(newName, newConfig);
    } else if (serverSource === 'global') {
      // Global MCP update
      if (nameChanged) {
        await removeGlobalMcpServer(serverName);
      }
      await addGlobalMcpServer(newName, newConfig);
    } else if (serverSource === 'project') {
      // Project MCP update
      if (nameChanged) {
        await removeMcpServerFromProject(serverName);
      }
      await copyMcpServerToProject(newName, newConfig, 'mcp');
    }

    closeMcpEditModal();
    showRefreshToast(t('mcp.editModal.saved', { name: newName }), 'success');
  } catch (err) {
    console.error('Failed to save MCP edit:', err);
    showRefreshToast(t('mcp.editModal.saveFailed') + ': ' + err.message, 'error');
  }
}

async function deleteMcpFromEdit() {
  const { serverName, serverSource, cliType } = mcpEditContext;

  if (!confirm(t('mcp.editModal.deleteConfirm', { name: serverName }))) {
    return;
  }

  try {
    if (cliType === 'codex') {
      await removeCodexMcpServer(serverName);
    } else if (serverSource === 'global') {
      await removeGlobalMcpServer(serverName);
    } else if (serverSource === 'project') {
      await removeMcpServerFromProject(serverName);
    }

    closeMcpEditModal();
    showRefreshToast(t('mcp.editModal.deleted', { name: serverName }), 'success');
  } catch (err) {
    console.error('Failed to delete MCP:', err);
    showRefreshToast(t('mcp.editModal.deleteFailed') + ': ' + err.message, 'error');
  }
}

// ========================================
// MCP Template Management Functions
// ========================================

let mcpTemplates = [];

/**
 * Load all MCP templates from API
 */
async function loadMcpTemplates() {
  try {
    const response = await fetch('/api/mcp-templates');
    const data = await response.json();

    if (data.success) {
      mcpTemplates = data.templates || [];
      console.log('[MCP Templates] Loaded', mcpTemplates.length, 'templates');
    } else {
      console.error('[MCP Templates] Failed to load:', data.error);
      mcpTemplates = [];
    }

    return mcpTemplates;
  } catch (error) {
    console.error('[MCP Templates] Error loading templates:', error);
    mcpTemplates = [];
    return [];
  }
}

/**
 * Save MCP server configuration as a template
 */
async function saveMcpAsTemplate(serverName, serverConfig) {
  try {
    // Prompt for template name and description
    const templateName = prompt(t('mcp.enterTemplateName'), serverName);
    if (!templateName) return;

    const description = prompt(t('mcp.enterTemplateDesc'), `Template for ${serverName}`);

    const payload = {
      name: templateName,
      description: description || '',
      serverConfig: serverConfig,
      category: 'user'
    };

    const response = await fetch('/api/mcp-templates', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

    const data = await response.json();

    if (data.success) {
      showRefreshToast(t('mcp.templateSaved', { name: templateName }), 'success');
      await loadMcpTemplates();
      await renderMcpManager(); // Refresh view
    } else {
      showRefreshToast(t('mcp.templateSaveFailed', { error: data.error }), 'error');
    }
  } catch (error) {
    console.error('[MCP] Save template error:', error);
    showRefreshToast(t('mcp.templateSaveFailed', { error: error.message }), 'error');
  }
}

/**
 * Install MCP server from template
 */
async function installFromTemplate(templateName, scope = 'project') {
  try {
    // Find template
    const template = mcpTemplates.find(t => t.name === templateName);
    if (!template) {
      showRefreshToast(t('mcp.templateNotFound', { name: templateName }), 'error');
      return;
    }

    // Prompt for server name (default to template name)
    const serverName = prompt(t('mcp.enterServerName'), templateName);
    if (!serverName) return;

    // Install based on scope
    if (scope === 'project') {
      await copyMcpServerToProject(serverName, template.serverConfig);
    } else if (scope === 'global') {
      await addGlobalMcpServer(serverName, template.serverConfig);
    }

    showRefreshToast(t('mcp.templateInstalled', { name: serverName }), 'success');
    await renderMcpManager();
  } catch (error) {
    console.error('[MCP] Install from template error:', error);
    showRefreshToast(t('mcp.templateInstallFailed', { error: error.message }), 'error');
  }
}

/**
 * Delete MCP template
 */
async function deleteMcpTemplate(templateName) {
  try {
    const response = await fetch(`/api/mcp-templates/${encodeURIComponent(templateName)}`, {
      method: 'DELETE'
    });

    const data = await response.json();

    if (data.success) {
      showRefreshToast(t('mcp.templateDeleted', { name: templateName }), 'success');
      await loadMcpTemplates();
      await renderMcpManager();
    } else {
      showRefreshToast(t('mcp.templateDeleteFailed', { error: data.error }), 'error');
    }
  } catch (error) {
    console.error('[MCP] Delete template error:', error);
    showRefreshToast(t('mcp.templateDeleteFailed', { error: error.message }), 'error');
  }
}

// ========== Global Exports for onclick handlers ==========
// Expose functions to global scope to support inline onclick handlers
window.openCodexMcpCreateModal = openCodexMcpCreateModal;
window.closeMcpEditModal = closeMcpEditModal;
window.saveMcpEdit = saveMcpEdit;
window.deleteMcpFromEdit = deleteMcpFromEdit;
window.saveMcpAsTemplate = saveMcpAsTemplate;
