fix(coding-agent/acp): preserve project-over-user precedence in mcp builtin

Addresses codex P2 review feedback on #1015:

- getMcpConfiguredServers (powers /mcp list, /mcp test, /mcp resources,
  /mcp prompts): iterate project config first so when the same server
  name is defined in both scopes the entry shown matches the one the
  runtime actually loads. Matches discovery/builtin.ts where the loader
  pushes project paths before user paths and capability dedupe is
  first-wins.
- handleEnableDisableCommand (/mcp enable, /mcp disable): check the
  project file before the user file so toggling a duplicated name flips
  the effective entry. Previously '/mcp disable foo' reported success
  while the active project foo stayed enabled.
This commit is contained in:
can1357
2026-05-13 05:10:24 +02:00
parent b1b6299639
commit d726ea3ab5
@@ -102,14 +102,14 @@ async function getMcpConfiguredServers(
const [userConfig, projectConfig] = await Promise.all([readMCPConfigFile(userPath), readMCPConfigFile(projectPath)]);
const servers: Array<{ name: string; config: MCPServerConfig; scope: AcpMcpScope }> = [];
const seen = new Set<string>();
for (const [name, config] of Object.entries(userConfig.mcpServers ?? {})) {
for (const [name, config] of Object.entries(projectConfig.mcpServers ?? {})) {
if (config.enabled !== false) {
servers.push({ name, config, scope: "user" });
servers.push({ name, config, scope: "project" });
seen.add(name);
}
}
for (const [name, config] of Object.entries(projectConfig.mcpServers ?? {})) {
if (!seen.has(name) && config.enabled !== false) servers.push({ name, config, scope: "project" });
for (const [name, config] of Object.entries(userConfig.mcpServers ?? {})) {
if (!seen.has(name) && config.enabled !== false) servers.push({ name, config, scope: "user" });
}
return servers;
}
@@ -432,16 +432,16 @@ async function handleEnableDisableCommand(verb: "enable" | "disable", rest: stri
readMCPConfigFile(userPath),
readMCPConfigFile(projectPath),
]);
if (userConfig.mcpServers?.[name] !== undefined) {
await updateMCPServer(userPath, name, { ...userConfig.mcpServers[name], enabled } as MCPServerConfig);
await runtime.output(`Server "${name}" ${enabled ? "enabled" : "disabled"} (user config).`);
return commandConsumed();
}
if (projectConfig.mcpServers?.[name] !== undefined) {
await updateMCPServer(projectPath, name, { ...projectConfig.mcpServers[name], enabled } as MCPServerConfig);
await runtime.output(`Server "${name}" ${enabled ? "enabled" : "disabled"} (project config).`);
return commandConsumed();
}
if (userConfig.mcpServers?.[name] !== undefined) {
await updateMCPServer(userPath, name, { ...userConfig.mcpServers[name], enabled } as MCPServerConfig);
await runtime.output(`Server "${name}" ${enabled ? "enabled" : "disabled"} (user config).`);
return commandConsumed();
}
const disabledList = await readDisabledServers(userPath);
if (!enabled || disabledList.includes(name)) {
await setServerDisabled(userPath, name, !enabled);