agentscope-ai / agentscope-ai/agentscope-java
Harness: preserve MCP client ownership across Toolkit.copy and close clients on agent shutdown
- Vorherrschende Sprache
- Java
- Sterne
- 5.6k
- Forks
- 1.3k
- Ø Merge
- 4 T. 12 Std.
- Gemergte PRs (30 T.)
- 77
Beschreibung
## 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.
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.