* Surgically drop `mcp.codegraph` from one config file. Leaves sibling * servers, comments, and formatting untouched; drops an emptied `mcp` * wrapper too. Shared by uninstall and the legacy-%APPDATA% sweep.
(file: string)
| 231 | * wrapper too. Shared by uninstall and the legacy-%APPDATA% sweep. |
| 232 | */ |
| 233 | function removeMcpEntryAt(file: string): WriteResult['files'][number] { |
| 234 | if (!fs.existsSync(file)) return { path: file, action: 'not-found' }; |
| 235 | const text = readConfigText(file); |
| 236 | const config = parseConfig(text); |
| 237 | if (!config.mcp?.codegraph) return { path: file, action: 'not-found' }; |
| 238 | |
| 239 | let edits = modify(text, ['mcp', 'codegraph'], undefined, { |
| 240 | formattingOptions: FORMATTING, |
| 241 | }); |
| 242 | let updated = applyEdits(text, edits); |
| 243 | |
| 244 | // If `mcp` is now an empty object, drop the wrapper too. |
| 245 | const afterParsed = parseConfig(updated); |
| 246 | if (afterParsed.mcp && typeof afterParsed.mcp === 'object' && |
| 247 | Object.keys(afterParsed.mcp).length === 0) { |
| 248 | edits = modify(updated, ['mcp'], undefined, { formattingOptions: FORMATTING }); |
| 249 | updated = applyEdits(updated, edits); |
| 250 | } |
| 251 | |
| 252 | atomicWriteFileSync(file, updated); |
| 253 | return { path: file, action: 'removed' }; |
| 254 | } |
| 255 | |
| 256 | /** |
| 257 | * Remove whatever a pre-#535 install left in `%APPDATA%/opencode` — an MCP |
no test coverage detected