[codex] fix MCP management lifecycle (#1144)

* feat(mcp): add MCP server management UI

- Server CRUD: add/edit/remove with YAML/JSON Monaco editor
- raw_config passthrough: zero field loss on edit/toggle
- tool_details embedding: single-request card data (1+N → 1)
- Auto-retry exponential backoff (2s→32s, max 5 retries)
- Route safety guards (hasRoute) for dynamic sidebar
- i18n: 9 languages (de/en/es/fr/ja/ko/pt/zh/zh-TW)
- 19 unit tests + 8 UX browser tests
- 35 files, +2933 lines

* fix mcp management lifecycle

---------

Co-authored-by: Crafter-feng <succeed_happu@163.com>
This commit is contained in:
ekko
2026-05-30 11:06:08 +08:00
committed by GitHub
parent 675ddb8282
commit b015e70b9d
37 changed files with 2717 additions and 7 deletions
+27
View File
@@ -59,6 +59,7 @@ function makeContext(state: any, commandResult: Record<string, unknown> = {
const runQueuedItem = vi.fn()
const bridge = {
command: vi.fn(async () => commandResult),
mcpReload: vi.fn(async () => ({ ok: true, message: 'MCP servers reloaded' })),
status: vi.fn(async () => ({
exists: true,
running: false,
@@ -303,4 +304,30 @@ describe('plan session command', () => {
}),
}))
})
it('rejects MCP reload while the session is running', async () => {
const state = { messages: [], isWorking: true, events: [], queue: [] }
const { bridge, namespaceEmit, runQueuedItem, sessionMap, socket, nsp } = makeContext(state)
const { handleSessionCommand, parseSessionCommand } = await import('../../packages/server/src/services/hermes/run-chat/session-command')
const command = parseSessionCommand('/reload-mcp github')!
await handleSessionCommand('session-1', command, {
nsp: nsp as any,
socket: socket as any,
sessionMap,
bridge: bridge as any,
profile: 'default',
runQueuedItem,
})
expect(bridge.mcpReload).not.toHaveBeenCalled()
expect(runQueuedItem).not.toHaveBeenCalled()
expect(namespaceEmit).toHaveBeenCalledWith('session.command', expect.objectContaining({
command: 'reload-mcp',
ok: false,
action: 'reload-mcp',
terminal: false,
message: 'MCP reload can only run while the session is idle. Wait for the current run to finish or abort it first.',
}))
})
})