(options: {
verbose?: boolean
})
| 204 | * @returns Record of MCP server configurations keyed by server name |
| 205 | */ |
| 206 | export function loadMCPConfigSync(options: { |
| 207 | verbose?: boolean |
| 208 | }): LoadedMCPConfig { |
| 209 | const { verbose = false } = options |
| 210 | |
| 211 | const mergedConfig: LoadedMCPConfig = { |
| 212 | mcpServers: {}, |
| 213 | _sourceFilePath: '', |
| 214 | } |
| 215 | |
| 216 | const mcpConfigDirs = getDefaultMcpConfigDirs() |
| 217 | |
| 218 | for (const dir of mcpConfigDirs) { |
| 219 | const configPath = path.join(dir, MCP_CONFIG_FILE_NAME) |
| 220 | |
| 221 | try { |
| 222 | if (!fs.existsSync(configPath)) { |
| 223 | continue |
| 224 | } |
| 225 | |
| 226 | const content = fs.readFileSync(configPath, 'utf8') |
| 227 | const rawConfig = JSON.parse(content) |
| 228 | const parseResult = mcpFileSchema.safeParse(rawConfig) |
| 229 | |
| 230 | if (!parseResult.success) { |
| 231 | if (verbose) { |
| 232 | console.error( |
| 233 | `Invalid mcp.json at ${configPath}: ${parseResult.error.message}`, |
| 234 | ) |
| 235 | } |
| 236 | continue |
| 237 | } |
| 238 | |
| 239 | const parsedConfig = parseResult.data |
| 240 | |
| 241 | // Resolve environment variable references |
| 242 | try { |
| 243 | resolveMcpConfigEnv(parsedConfig) |
| 244 | } catch (error) { |
| 245 | if (verbose) { |
| 246 | console.error(error instanceof Error ? error.message : String(error)) |
| 247 | } |
| 248 | continue |
| 249 | } |
| 250 | |
| 251 | // Merge MCP servers (later directories override earlier ones) |
| 252 | for (const [serverName, serverConfig] of Object.entries( |
| 253 | parsedConfig.mcpServers, |
| 254 | )) { |
| 255 | mergedConfig.mcpServers[serverName] = serverConfig |
| 256 | } |
| 257 | |
| 258 | // Track the last successfully loaded config path |
| 259 | if (Object.keys(parsedConfig.mcpServers).length > 0) { |
| 260 | mergedConfig._sourceFilePath = configPath |
| 261 | } |
| 262 | } catch (error) { |
| 263 | if (verbose) { |
no test coverage detected