[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
@@ -711,6 +711,51 @@ assert response["ok"] is True, response
assert captured["endpoint"] == "ipc:///tmp/worker.sock", captured
assert captured["req"] == {"action": "chat"}, captured
assert captured["timeout"] == 310, captured
`)
})
it('awaits MCP server shutdown without holding the MCP registry lock', () => {
runPython(String.raw`
${harness}
import asyncio
lock = threading.Lock()
servers = {}
events = []
class FakeMcpTask:
async def shutdown(self):
events.append("shutdown-started")
acquired = lock.acquire(blocking=False)
events.append(("lock-free-during-shutdown", acquired))
if acquired:
lock.release()
await asyncio.sleep(0)
events.append("shutdown-finished")
task = FakeMcpTask()
servers["github"] = task
def run_on_mcp_loop(factory, timeout=30):
events.append(("timeout", timeout))
asyncio.run(factory())
result = bridge.BridgeServer._shutdown_mcp_server(
"github",
servers,
lock,
run_on_mcp_loop,
)
assert result is True, result
assert "github" not in servers, servers
assert events == [
("timeout", 15),
"shutdown-started",
("lock-free-during-shutdown", True),
"shutdown-finished",
], events
`)
})
})