Skip to content

feat: Support mcp task#3140

Open
Yeaury wants to merge 6 commits intoalibaba:masterfrom
Yeaury:feature/mcp-tasks-support
Open

feat: Support mcp task#3140
Yeaury wants to merge 6 commits intoalibaba:masterfrom
Yeaury:feature/mcp-tasks-support

Conversation

@Yeaury
Copy link
Copy Markdown
Contributor

@Yeaury Yeaury commented Feb 26, 2026

概述

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:任务感知工具注册与分发,支持两种执行模式

    • 任务增强模式:客户端发送 task 元数据 → 创建任务立即返回
    • 自动轮询模式:无 task 元数据 → 内部创建任务并轮询至完成
  • 新增 CreateTaskContext / DefaultCreateTaskContext:工具管理任务生命周期的 API(创建/完成/失败/取消/设置输入等待)

    • 新增 ToolCallbackCreateTaskHandler:将 ToolCallback 适配为任务模式,包含三层协作式取消检查(执行前/执行中/执行后)
    • 新增 TaskAwareToolSpecification:任务感知工具规格定义

协议层扩展

  • McpSchema 新增类型:Task、TaskStatus(WORKING/INPUT_REQUIRED/COMPLETED/FAILED/CANCELLED)、TaskMetadata、RelatedTaskMetadata、TaskSupportMode(FORBIDDEN/OPTIONAL/REQUIRED)、ToolExecution
  • 新增协议方法:tasks/get、tasks/result、tasks/list、tasks/cancel、notifications/tasks/status
  • ServerCapabilities 新增 TaskCapabilities(list/cancel/toolsCall)

工具集成

  • @Tool 注解新增 taskSupport 属性,默认 FORBIDDEN

  • 5 个流式工具(WatchTool、TraceTool、StackTool、MonitorTool、TimeTunnelTool)标记为 taskSupport = OPTIONAL

    • AbstractArthasTool 集成取消检查器,在轮询循环中检测任务取消
  • 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 命令

Copy link
Copy Markdown
Collaborator

@hengyunabc hengyunabc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Yeaury
Copy link
Copy Markdown
Contributor Author

Yeaury commented Apr 16, 2026

我在当前的 MCP Tasks 实现中发现了三个问题:任务结果/取消流程中的两个正确性错误和一个运行时工具注册表不一致。

非常感谢 @hengyunabc 的详细 review!感谢您花时间指出这些问题,我会尽快修复这三个问题并推送更新

Yeaury added a commit to Yeaury/arthas that referenced this pull request Apr 16, 2026
- 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
@Yeaury Yeaury force-pushed the feature/mcp-tasks-support branch from ca8245a to af3d61d Compare April 16, 2026 13:42
@Yeaury Yeaury changed the title feat: 实现 MCP Tasks 支持 feat: Support mcp task Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants