agentscope-ai / agentscope-ai/agentscope-java

Harness: preserve MCP client ownership across Toolkit.copy and close clients on agent shutdown

オープン
#2,139 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
area/harness enhancement
主要言語
Java
スター
5.6k
フォーク
1.3k
平均マージ
4日 12時間
マージ済み PR(30日)
77

説明

## Problem

Harness registers workspace `tools.json` MCP clients into `agentToolkit`, then `ReActAgent.Builder` creates the final toolkit through `toolkit.copy()`. `Toolkit.copy()` copies registered tool functions/groups but not `McpClientManager` ownership. The final agent can invoke copied MCP tool functions, but it cannot enumerate or close the registrar-owned client.

`HarnessAgent.close()` shuts down the task repository/workspace index/delegate only; it does not close MCP clients. For stdio transport the child server process remains alive after runtime close.

Observed against `e3a412ed2cc944e401da861c8d5e464b967724e9` with a real JSON-RPC stdio fixture:

1. `tools.json -> McpServerRegistrar -> Toolkit` initializes and calls the fixture successfully.
2. `runtime.agent().getToolkit().removeMcpClient("fixture")` cannot remove the registrar client after the toolkit copy; the MCP tool and process remain.
3. `JCodeHarnessRuntime.close() -> HarnessAgent.close() -> ReActAgent.close()` leaves the fixture process alive.

## Expected ownership contract

The final Harness/agent lifecycle that exposes MCP tools must own the corresponding clients and close them exactly once.

Possible design:

- make `Toolkit` implement an explicit async close/close-all contract and expose a read-only client inventory;
- preserve client ownership across `Toolkit.copy()` using a shared reference-counted lifecycle owner, or avoid copying an already-registered MCP toolkit;
- ensure removing a client removes its tools/groups and closes its transport;
- call close-all from `HarnessAgent.close()` / final agent close;
- define ownership for parent/child toolkit copies so one child cannot close a client still used by another, while the last owner always closes it.

A public list plus application-side loops is insufficient if the final copied toolkit does not retain the original manager.

## Acceptance

1. Real stdio process exits after final Harness close.
2. `removeMcpClient(name)` on the final exposed toolkit removes tools and closes transport.
3. Parent/child toolkit copies have deterministic shared/isolated ownership and no double-close.
4. Failed or partially initialized registration closes the created client.
5. SSE/HTTP clients also close subscriptions/resources.
6. Repeated close is idempotent.
7. Product hosts need no client/process registry or PID cleanup.

The application-side fixture currently performs PID teardown only in test cleanup; no production workaround is installed because MCP lifecycle belongs to AgentScope Toolkit/Harness.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。