()
| 1610 | // Build McpServerStatus[] for control responses. Shared by mcp_status and |
| 1611 | // reload_plugins handlers. Reads closure state: sdkClients, dynamicMcpState. |
| 1612 | function buildMcpServerStatuses(): McpServerStatus[] { |
| 1613 | const currentAppState = getAppState() |
| 1614 | const currentMcpClients = currentAppState.mcp.clients |
| 1615 | const allMcpTools = uniqBy( |
| 1616 | [...currentAppState.mcp.tools, ...dynamicMcpState.tools], |
| 1617 | 'name', |
| 1618 | ) |
| 1619 | const existingNames = new Set([ |
| 1620 | ...currentMcpClients.map(c => c.name), |
| 1621 | ...sdkClients.map(c => c.name), |
| 1622 | ]) |
| 1623 | return [ |
| 1624 | ...currentMcpClients, |
| 1625 | ...sdkClients, |
| 1626 | ...dynamicMcpState.clients.filter(c => !existingNames.has(c.name)), |
| 1627 | ].map(connection => { |
| 1628 | let config |
| 1629 | if ( |
| 1630 | connection.config.type === 'sse' || |
| 1631 | connection.config.type === 'http' |
| 1632 | ) { |
| 1633 | config = { |
| 1634 | type: connection.config.type, |
| 1635 | url: connection.config.url, |
| 1636 | headers: connection.config.headers, |
| 1637 | oauth: connection.config.oauth, |
| 1638 | } |
| 1639 | } else if (connection.config.type === 'claudeai-proxy') { |
| 1640 | config = { |
| 1641 | type: 'claudeai-proxy' as const, |
| 1642 | url: connection.config.url, |
| 1643 | id: connection.config.id, |
| 1644 | } |
| 1645 | } else if ( |
| 1646 | connection.config.type === 'stdio' || |
| 1647 | connection.config.type === undefined |
| 1648 | ) { |
| 1649 | config = { |
| 1650 | type: 'stdio' as const, |
| 1651 | command: connection.config.command, |
| 1652 | args: connection.config.args, |
| 1653 | } |
| 1654 | } |
| 1655 | const serverTools = |
| 1656 | connection.type === 'connected' |
| 1657 | ? filterToolsByServer(allMcpTools, connection.name).map(tool => ({ |
| 1658 | name: tool.mcpInfo?.toolName ?? tool.name, |
| 1659 | annotations: { |
| 1660 | readOnly: tool.isReadOnly({}) || undefined, |
| 1661 | destructive: tool.isDestructive?.({}) || undefined, |
| 1662 | openWorld: tool.isOpenWorld?.({}) || undefined, |
| 1663 | }, |
| 1664 | })) |
| 1665 | : undefined |
| 1666 | // Capabilities passthrough with allowlist pre-filter. The IDE reads |
| 1667 | // experimental['claude/channel'] to decide whether to show the |
| 1668 | // Enable-channel prompt — only echo it if channel_enable would |
| 1669 | // actually pass the allowlist. Not a security boundary (the |
no test coverage detected