Skip to content

[Feat] Let run_agent run as an MCP task (2025-11-25 experimental tasks on the 1.x SDK) - #106

Draft
Birfy wants to merge 1 commit into
mainfrom
issue-102-mcp-tasks
Draft

Birfy wants to merge 1 commit into
mainfrom
issue-102-mcp-tasks

Conversation

@Birfy

@Birfy Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

Required human contributor answers

Per the repo owner's (Danyang, @Birfy) standing instruction, these are filled from the issue (#102) instead of waiting for separate human answers.

  1. What outcome are you trying to achieve?

    Answer: A host can start a long run_agent without holding one tools/call request open for the whole browser budget, then poll and cancel it ([MCP] Adopt MCP Tasks so long run_agent can outlive the host session #102).

  2. What is the highest-leverage variable for that outcome?

    Answer: Whether s1a-mcp can answer a task-augmented tools/call while staying on mcp<2 ([Deps] Bound mcp below 2 and record what blocks the move to the 2026-07-28 SDK #74).

  3. How will this work move that variable rather than create busywork?

    Answer: It does the spike from scope item 1 and lands the path the 1.x SDK supports, with contract tests for the task path, the plain path and cancel, and docs that say what is and is not verified.

  4. Who is the customer or user, and what do they actually need?

    Answer: People calling S1A agents from MCP hosts (Claude Code, Codex) whose tool timeouts are shorter than a browser run.

After answering the four questions: is a PR needed at all to achieve this outcome?

Human decision and rationale (or explicit source reference): Yes; #102 scopes this as one opt-in PR.

For a bug fix: link actual observed failure evidence.

Evidence: Not a bug fix: a new opt-in call mode.

Why

run_agent can take minutes (Allrecipes budgets 300 s), and today a host must keep the request open the whole time. Closes #102.

How

Spike result (scope item 1): the installed mcp 1.30.0 implements tasks as the 2025-11-25 experimental API (SEP-1686: capabilities.tasks, params.task, tasks/get|result|list|cancel). It does not implement the 2026-07-28 extension form, and it marks the experimental API deprecated ("tasks (SEP-1686) were removed from the MCP specification and are expected to return as a separate MCP extension"). So tasks can land on 1.x, but only in the 2025-11-25 shape; a host that speaks only the extension form will keep the plain call. The mcp 2 move from #74 is not needed for this, and it would not give the extension form either.

Start with s1a/mcp_server.py, then TestRunAgentAsTask in tests/test_mcp_server.py.

  • _TaskServer(FastMCP) marks run_agent execution.taskSupport: "optional" in tools/list. A tools/call without task takes FastMCP's unchanged path. With task, it calls run_task, returns a CreateTaskResult at once, and runs the same FastMCP tool call in the session's task group.
  • Progress messages (episode N/M, step N/M) become the task's statusMessage via update_status (rate-bounded like progress notifications; the limiter is now shared as _rate_bounded).
  • tasks/cancel wraps the SDK's handler (session scope and terminal-state checks) and then cancels the run's anyio.CancelScope, which is the same cancellation notifications/cancelled triggers today, so the slot is freed, the browser closed and the cancellation recorded ([MCP] Keep long run_agent calls inside host tool timeouts: progress, bounded lock wait, cancellation, documented settings #83).
  • _TaskStore(InMemoryTaskStore) keeps a cancelled task cancelled: the SDK otherwise raises "Cannot transition from terminal status" when the unwinding run completes.
  • A task's ttl is raised to at least 1 h, because the in-memory store counts it from creation and the client default (60 s) would drop a run part-way.
  • Bad flags and the busy refusal complete the task with an isError result (as they are the plain call's result). A task call of decide or list_agents is a -32601 protocol error.

What

  • s1a-mcp advertises the tasks capability; run_agent is task-optional. No change for clients that send no task.
  • Docs: docs/skills.md § Long runs as MCP tasks (what is and is not verified), docs/architecture.md § MCP SDK 2.x (the port must move or drop this path), CHANGELOG.
  • No host flags are documented: no host has been verified against this path yet, so the raised tool timeout advice stays.

Verification

  • uv run ruff format --check . && uv run ruff check . && uv run ty check (all pass)
  • uv run pytest -q: 1356 passed, 123 skipped; scripts/smoke.sh: smoke: ok
  • CHANGELOG.md and the docs say what the code does now

New tests (in-memory client using the SDK's session.experimental task calls): capability and taskSupport advertisement; task returns at once, working with episode 1/2, holds the run slot, then completed with the summary; a real counter run as a task returns the same summary and job folder; bad flags and busy refusal end as isError results; tasks/cancel tears the browser and session down, frees the slot, leaves the task cancelled; task call of decide is -32601.

Demo / evidence

  • Video link, or exemption/blocker with follow-up: N/A for a video (MCP protocol change, no application run). Blocker for "verified host": no Claude Code / Codex run against this path yet; kept as draft until one is checked or a maintainer accepts that.
  • Application/task → agent actions → independently checked result: contract tests only.
  • System1-Agents / System1-Omni commits, checkpoint and worker/frontend provenance: base main 113ef26; no System1-Omni involved.

…SDK)

A task-augmented run_agent returns a task id at once; tasks/get reports the
latest episode or step, tasks/result the usual result and tasks/cancel stops the
run through the existing cancellation path. Plain calls are unchanged; decide and
list_agents refuse task calls with -32601.

Closes #102
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.

[MCP] Adopt MCP Tasks so long run_agent can outlive the host session

1 participant