Conversation
… negotiation - Implemented MCP Tasks capability (tasks/list, tasks/cancel, tasks/result)
hengyunabc
left a comment
There was a problem hiding this comment.
I found three issues in the current MCP Tasks implementation: two correctness bugs in task result/cancel flows and one runtime tool registry inconsistency.
|
|
||
| if (task.isTerminal()) { | ||
| logger.debug("defaultGetTaskResult: Task {} is terminal, fetching result", taskId); | ||
| return fetchTaskResult(taskId, sessionId); |
There was a problem hiding this comment.
defaultGetTaskResult() assumes every terminal task has a stored payload and unconditionally fetches it here. That is not true in this PR: the error path only flips the task to FAILED, and cancellation also reaches a terminal status without storing a payload. A tool error or user cancellation will therefore fall through to Task result not found/null instead of a usable task result. Either persist an error/cancel payload or make tasks/result handle terminal tasks without payloads explicitly.
| } | ||
|
|
||
| return this.taskStore.requestCancellation(taskId, ctx.sessionId()) | ||
| .thenApply(task -> (McpSchema.Result) McpSchema.CancelTaskResult.fromTask(task)); |
There was a problem hiding this comment.
requestCancellation() can return null when the task id does not exist or is not visible to the session. Passing that directly into CancelTaskResult.fromTask(task) turns a normal client error into a server-side NPE instead of an INVALID_PARAMS response for an unknown/stale task id.
| return future; | ||
| String toolName = callToolRequest.getName(); | ||
|
|
||
| McpServerFeatures.ToolSpecification normalTool = this.toolsByName.get(toolName); |
There was a problem hiding this comment.
tools/call now uses the toolsByName fast path here, but addTool() never inserts into that map and removeTool() never evicts from it. After this change, a tool added at runtime can appear in tools/list but still be uncallable, while a removed tool may remain callable through a stale map entry.
非常感谢 @hengyunabc 的详细 review!感谢您花时间指出这些问题,我会尽快修复这三个问题并推送更新 |
- failTask now stores CallToolResult payload via storeTaskResult so tasks/result returns meaningful responses for FAILED tasks; CANCELLED tasks get a synthetic fallback in fetchTaskResult and pollTaskUntilTerminal - handleCancelTask guards against null from requestCancellation for unknown/expired task IDs, returning INVALID_PARAMS instead of NPE - addTool/removeTool now keep toolsByName in sync with the tools list Refs alibaba#3140 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- failTask now stores CallToolResult payload via storeTaskResult so tasks/result returns meaningful responses for FAILED tasks; CANCELLED tasks get a synthetic fallback in fetchTaskResult and pollTaskUntilTerminal - handleCancelTask guards against null from requestCancellation for unknown/expired task IDs, returning INVALID_PARAMS instead of NPE - addTool/removeTool now keep toolsByName in sync with the tools list
ca8245a to
af3d61d
Compare
概述
Ref #3099
为 Arthas MCP Server 实现完整的 MCP Tasks 协议支持,使 watch、trace、stack、monitor、tt 等长时间运行的诊断命令能够以异步任务方式执行,支持任务状态查询、结果获取和协作式取消。
变更内容
任务管理核心
TaskStore/InMemoryTaskStore:基于 ConcurrentSkipListMap 的任务持久化,支持 TTL 自动清理、游标分页、会话隔离TaskManager/DefaultTaskManager:任务编排管理器,通过 5 个生命周期方法(processInboundRequest/processOutboundRequest/processInboundResponse/processOutboundNotification/onClose)与协议层交互NullTaskManager:未启用任务时的空实现TaskMessageQueue/InMemoryTaskMessageQueue:INPUT_REQUIRED 状态下的 side-channel 消息队列任务工具处理
新增
ServerTaskToolHandler:任务感知工具注册与分发,支持两种执行模式新增
CreateTaskContext/DefaultCreateTaskContext:工具管理任务生命周期的 API(创建/完成/失败/取消/设置输入等待)ToolCallbackCreateTaskHandler:将 ToolCallback 适配为任务模式,包含三层协作式取消检查(执行前/执行中/执行后)TaskAwareToolSpecification:任务感知工具规格定义协议层扩展
McpSchema新增类型:Task、TaskStatus(WORKING/INPUT_REQUIRED/COMPLETED/FAILED/CANCELLED)、TaskMetadata、RelatedTaskMetadata、TaskSupportMode(FORBIDDEN/OPTIONAL/REQUIRED)、ToolExecutionServerCapabilities新增 TaskCapabilities(list/cancel/toolsCall)工具集成
@Tool注解新增taskSupport属性,默认 FORBIDDEN5 个流式工具(WatchTool、TraceTool、StackTool、MonitorTool、TimeTunnelTool)标记为
taskSupport = OPTIONALAbstractArthasTool集成取消检查器,在轮询循环中检测任务取消StreamableToolUtils新增 CancellationChecker 支持新增
ToolContextKeys统一上下文键名常量服务器启动重构
ArthasMcpServer重构为按 taskSupport 分类工具,分别注册普通工具和任务感知工具ArthasCommandSessionManager管理每个任务的隔离会话McpNettyServer集成 ServerTaskToolHandler,注册任务相关请求处理器任务生命周期
Client: tools/call (带 task: {ttl: 30000})
→ 创建任务 → 立即返回 CreateTaskResult
→ 后台异步执行工具
Client: tasks/get (轮询状态)
→ 返回 Task{status: WORKING/COMPLETED/FAILED/...}
Client: tasks/result (获取结果,阻塞至完成)
→ 返回 CallToolResult
Client: tasks/cancel (请求取消)
→ 设置取消标志 → 工具轮询循环检测到 → 中断 Arthas 命令