ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SEP-2663 Tasks 扩展实战:MCP 长任务从轮询到推送的配置骨架

SEP-2663 Tasks 扩展实战:MCP 长任务从轮询到推送的配置骨架 1. 为什么你的 MCP 长任务还在傻等轮询如果你正在用 MCP 跑分钟级甚至小时级的任务大概率写过这样的循环调一次tools/call拿到一个task_id然后sleep(2)再查一次状态直到status变成completed。这套轮询逻辑能跑但代价很实在——连接被反复占用、进度条只能靠猜、客户端和服务端都在做无用功。SEP-2663 Tasks 扩展想解决的就是这件事。它给 MCP 补上了任务生命周期语义queued → running → completed / failed / cancelled再配合 Progress notifications 和 Subscriptions/listen让服务端在任务状态变化时主动把结果推给客户端而不是客户端一遍遍问「好了没」。换句话说长任务的结果应该主动到达而不是你反复去捞。这篇面向已经用轮询等结果的开发者给出config.toml与settings.json里的 Tasks 推送配置骨架、CC Switch 切换验证步骤以及从轮询改成推送后可复现的验证动作。适合谁自建 Agent 平台、写过私有 job API、被长任务轮询折磨过的后端和工具链同学。读完你能拿到一套能直接抄的配置骨架并知道怎么确认推送真的生效了。2. TaoToken 前置把模型与任务通道接起来推送化改造不只是改客户端逻辑模型侧和任务通道得先通。我习惯用 TaoToken 做统一入口它的 API 地址是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。先在控制台建一个 Key后面config.toml和settings.json都要用到。拿 Key 的入口在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面把请求格式、鉴权头、错误码都列清楚了配置前扫一遍能省不少排障时间。如果你只是想先验证模型对话通不通可以用模型对话页快速试一条https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite。但本篇重点是 Tasks 推送模型对话只是前置确认别在这里停太久。注意Tasks 推送依赖服务端主动发消息所以你的 MCP Server 必须支持长连接或 SSE 通道。如果服务端还是纯无状态短请求推送配置写了也不会生效这点后面排障会再讲。3. 可复制配置config.toml 与 settings.json 骨架先给config.toml的骨架。这里的关键是把任务模式从poll切成push并声明订阅通道。字段名按你实际 Server 实现微调但结构可以直接抄[mcp] endpoint https://taotoken.net/api api_key sk-你的Key transport sse [mcp.tasks] mode push # 从 poll 改为 push task_id_field task_id status_field status subscribe_channel tasks/events progress_notifications true heartbeat_interval_ms 15000 reconnect_backoff_ms 2000 max_reconnect_attempts 5 [mcp.tasks.states] queued queued running running completed completed failed failed cancelled cancelledmode push是总开关subscribe_channel是客户端订阅的事件通道progress_notifications打开后服务端会推百分比或阶段。heartbeat_interval_ms用来保活reconnect_backoff_ms处理断线重连。再看settings.json这里管客户端行为重点是订阅回调和超时策略{ mcp: { tasks: { mode: push, subscribe: { channel: tasks/events, on_event: handleTaskEvent, auto_resubscribe: true }, timeout: { task_max_ms: 3600000, idle_ms: 120000 }, fallback: { enable_poll: false, poll_interval_ms: 5000 } } } }fallback.enable_poll建议先设false逼自己走通推送链路等稳定后再考虑作为兜底打开。task_max_ms给到一小时覆盖小时级任务。on_event指向你的事件处理函数收到completed时直接取结果收到running时更新进度。两个文件的分工要清楚config.toml管连接和任务语义settings.json管客户端订阅和超时。改完别急着跑先做下一步的切换验证。4. CC Switch 切换验证与推送成功结果CC Switch 用来在轮询和推送两套配置间切换方便对比。切换步骤第一步备份当前轮询配置避免改坏回不去。第二步把config.toml的mode改成pushsettings.json的fallback.enable_poll设false。第三步执行切换命令cc-switch --profile mcp-tasks-push --config ./config.toml --settings ./settings.json第四步确认切换生效cc-switch --status输出里应该看到mode: push和channel: tasks/events。如果还是poll说明 profile 没加载对检查路径。验证推送是否真的生效用一个可复现的动作发起一个长任务然后不要写轮询循环只监听事件。下面是一段最小验证代码import json from sseclient import SSEClient def handle_task_event(event): data json.loads(event.data) print(ftask{data[task_id]} status{data[status]}) if data[status] completed: print(结果:, data.get(result)) url https://taotoken.net/api/mcp/tasks/events client SSEClient(url, headers{Authorization: Bearer sk-你的Key}) for event in client: handle_task_event(event)成功结果长这样任务发起后终端先打印statusrunning可能带progress30任务完成后自动打印statuscompleted和结果。整个过程你没有发过一次查询请求。如果只看到running没有completed多半是服务端没推终态去排障章节对号入座。5. 本篇常见错排查推送配置写了但收不到事件。先确认transport是sse而不是普通 HTTP。纯短请求通道没有长连接服务端推不过来。再确认subscribe_channel和服务端实际通道名一致大小写和斜杠都算。收到 running 但永远等不到 completed。检查服务端任务状态机是否真的会写终态。有些实现只在内存里改状态进程重启就丢客户端自然等不到。另外看task_max_ms是不是设太短任务没跑完就被客户端超时断开了。断线后事件丢失。打开auto_resubscribe并把reconnect_backoff_ms调到合理值。如果服务端不支持断点续传重连后要主动拉一次当前状态做补偿别只依赖推送。CC Switch 切换后行为没变。大概率是 profile 缓存。执行cc-switch --status确认当前 profile必要时清缓存再切。还有一种情况是两个配置文件路径写反了config.toml和settings.json别搞混。轮询和推送同时开着导致重复处理。把fallback.enable_poll关掉或者确保事件处理函数幂等同一个task_id的completed只处理一次。6. 长期编码与 Agent 场景的下一步如果你只是偶尔跑长任务上面的配置够用了。但如果你在做长期编码、Agent 长跑这类场景任务数量和并发会明显上来这时候建议把任务通道和模型调用统一管理用 Coding Plan 把额度、并发和任务订阅放在一起规划https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite。我自己的做法是先把内部 job 模型抽象成可查询的task_id工具返回值区分同步结果和 task handle日志里带上task_id方便和链路追踪关联。这样等 SEP-2663 定稿时你只需要换配置不用推翻整套私有 job API。推送化改造现在做比 spec 定稿后再返工便宜得多。
返回列表