(
dynamicServers: Record<string, ScopedMcpServerConfig> = {},
extraDedupTargets: Promise<
Record<string, ScopedMcpServerConfig>
> = Promise.resolve({}),
)
| 1069 | * @returns Claude Code server configurations with appropriate scopes |
| 1070 | */ |
| 1071 | export async function getClaudeCodeMcpConfigs( |
| 1072 | dynamicServers: Record<string, ScopedMcpServerConfig> = {}, |
| 1073 | extraDedupTargets: Promise< |
| 1074 | Record<string, ScopedMcpServerConfig> |
| 1075 | > = Promise.resolve({}), |
| 1076 | ): Promise<{ |
| 1077 | servers: Record<string, ScopedMcpServerConfig> |
| 1078 | errors: PluginError[] |
| 1079 | }> { |
| 1080 | const { servers: enterpriseServers } = getMcpConfigsByScope('enterprise') |
| 1081 | |
| 1082 | // If an enterprise mcp config exists, do not use any others; this has exclusive control over all MCP servers |
| 1083 | // (enterprise customers often do not want their users to be able to add their own MCP servers). |
| 1084 | if (doesEnterpriseMcpConfigExist()) { |
| 1085 | // Apply policy filtering to enterprise servers |
| 1086 | const filtered: Record<string, ScopedMcpServerConfig> = {} |
| 1087 | |
| 1088 | for (const [name, serverConfig] of Object.entries(enterpriseServers)) { |
| 1089 | if (!isMcpServerAllowedByPolicy(name, serverConfig)) { |
| 1090 | continue |
| 1091 | } |
| 1092 | filtered[name] = serverConfig |
| 1093 | } |
| 1094 | |
| 1095 | return { servers: filtered, errors: [] } |
| 1096 | } |
| 1097 | |
| 1098 | // Load other scopes — unless the managed policy locks MCP to plugin-only. |
| 1099 | // Unlike the enterprise-exclusive block above, this keeps plugin servers. |
| 1100 | const mcpLocked = isRestrictedToPluginOnly('mcp') |
| 1101 | const noServers: { servers: Record<string, ScopedMcpServerConfig> } = { |
| 1102 | servers: {}, |
| 1103 | } |
| 1104 | const { servers: userServers } = mcpLocked |
| 1105 | ? noServers |
| 1106 | : getMcpConfigsByScope('user') |
| 1107 | const { servers: projectServers } = mcpLocked |
| 1108 | ? noServers |
| 1109 | : getMcpConfigsByScope('project') |
| 1110 | const { servers: localServers } = mcpLocked |
| 1111 | ? noServers |
| 1112 | : getMcpConfigsByScope('local') |
| 1113 | |
| 1114 | // Load plugin MCP servers |
| 1115 | const pluginMcpServers: Record<string, ScopedMcpServerConfig> = {} |
| 1116 | |
| 1117 | const pluginResult = await loadAllPluginsCacheOnly() |
| 1118 | |
| 1119 | // Collect MCP-specific errors during server loading |
| 1120 | const mcpErrors: PluginError[] = [] |
| 1121 | |
| 1122 | // Log any plugin loading errors - NEVER silently fail in production |
| 1123 | if (pluginResult.errors.length > 0) { |
| 1124 | for (const error of pluginResult.errors) { |
| 1125 | // Only log as MCP error if it's actually MCP-related |
| 1126 | // Otherwise just log as debug since the plugin might not have MCP servers |
| 1127 | if ( |
| 1128 | error.type === 'mcp-config-invalid' || |
no test coverage detected