( scope: 'project' | 'user' | 'local' | 'enterprise', )
| 886 | * @returns Servers with scope information and any validation errors |
| 887 | */ |
| 888 | export function getMcpConfigsByScope( |
| 889 | scope: 'project' | 'user' | 'local' | 'enterprise', |
| 890 | ): { |
| 891 | servers: Record<string, ScopedMcpServerConfig> |
| 892 | errors: ValidationError[] |
| 893 | } { |
| 894 | // Check if this source is enabled |
| 895 | const sourceMap: Record< |
| 896 | string, |
| 897 | 'projectSettings' | 'userSettings' | 'localSettings' |
| 898 | > = { |
| 899 | project: 'projectSettings', |
| 900 | user: 'userSettings', |
| 901 | local: 'localSettings', |
| 902 | } |
| 903 | |
| 904 | if (scope in sourceMap && !isSettingSourceEnabled(sourceMap[scope]!)) { |
| 905 | return { servers: {}, errors: [] } |
| 906 | } |
| 907 | |
| 908 | switch (scope) { |
| 909 | case 'project': { |
| 910 | const allServers: Record<string, ScopedMcpServerConfig> = {} |
| 911 | const allErrors: ValidationError[] = [] |
| 912 | |
| 913 | // Build list of directories to check |
| 914 | const dirs: string[] = [] |
| 915 | let currentDir = getCwd() |
| 916 | |
| 917 | while (currentDir !== parse(currentDir).root) { |
| 918 | dirs.push(currentDir) |
| 919 | currentDir = dirname(currentDir) |
| 920 | } |
| 921 | |
| 922 | // Process from root downward to CWD (so closer files have higher priority) |
| 923 | for (const dir of dirs.reverse()) { |
| 924 | const mcpJsonPath = join(dir, '.mcp.json') |
| 925 | |
| 926 | const { config, errors } = parseMcpConfigFromFilePath({ |
| 927 | filePath: mcpJsonPath, |
| 928 | expandVars: true, |
| 929 | scope: 'project', |
| 930 | }) |
| 931 | |
| 932 | // Missing .mcp.json in parent directories is expected, but malformed files should report errors |
| 933 | if (!config) { |
| 934 | const nonMissingErrors = errors.filter( |
| 935 | e => !e.message.startsWith('MCP config file not found'), |
| 936 | ) |
| 937 | if (nonMissingErrors.length > 0) { |
| 938 | logForDebugging( |
| 939 | `MCP config errors for ${mcpJsonPath}: ${jsonStringify(nonMissingErrors.map(e => e.message))}`, |
| 940 | { level: 'error' }, |
| 941 | ) |
| 942 | allErrors.push(...nonMissingErrors) |
| 943 | } |
| 944 | continue |
| 945 | } |
no test coverage detected