()
| 1256 | * @returns All server configurations with appropriate scopes |
| 1257 | */ |
| 1258 | export async function getAllMcpConfigs(): Promise<{ |
| 1259 | servers: Record<string, ScopedMcpServerConfig> |
| 1260 | errors: PluginError[] |
| 1261 | }> { |
| 1262 | // In enterprise mode, don't load claude.ai servers (enterprise has exclusive control) |
| 1263 | if (doesEnterpriseMcpConfigExist()) { |
| 1264 | return getClaudeCodeMcpConfigs() |
| 1265 | } |
| 1266 | |
| 1267 | // Kick off the claude.ai fetch before getClaudeCodeMcpConfigs so it overlaps |
| 1268 | // with loadAllPluginsCacheOnly() inside. Memoized — the awaited call below is a cache hit. |
| 1269 | const claudeaiPromise = fetchClaudeAIMcpConfigsIfEligible() |
| 1270 | const { servers: claudeCodeServers, errors } = await getClaudeCodeMcpConfigs( |
| 1271 | {}, |
| 1272 | claudeaiPromise, |
| 1273 | ) |
| 1274 | const { allowed: claudeaiMcpServers } = filterMcpServersByPolicy( |
| 1275 | await claudeaiPromise, |
| 1276 | ) |
| 1277 | |
| 1278 | // Suppress claude.ai connectors that duplicate an enabled manual server. |
| 1279 | // Keys never collide (`slack` vs `claude.ai Slack`) so the merge below |
| 1280 | // won't catch this — need content-based dedup by URL signature. |
| 1281 | const { servers: dedupedClaudeAi } = dedupClaudeAiMcpServers( |
| 1282 | claudeaiMcpServers, |
| 1283 | claudeCodeServers, |
| 1284 | ) |
| 1285 | |
| 1286 | // Merge with claude.ai having lowest precedence |
| 1287 | const servers = Object.assign({}, dedupedClaudeAi, claudeCodeServers) |
| 1288 | |
| 1289 | return { servers, errors } |
| 1290 | } |
| 1291 | |
| 1292 | /** |
| 1293 | * Parse and validate an MCP configuration object |
no test coverage detected