ordinary being eed7fa8f05
fix(mcp): fail durable tasks whose connection no longer resolves (#7058)
* fix(mcp): fail durable tasks whose connection no longer resolves

A personal MCP runtime name is derived from the server's complete definition, and a deployment task server belongs to the Gateway startup snapshot. Editing, disabling, or deleting a personal server while a durable task is in flight therefore makes the persisted server name unresolvable. McpTaskToolCaller raised LookupError, which the service classifies as transient: status polls and cancellation retried forever, leaving the task stuck in working and impossible to cancel.

Raise a dedicated McpTaskConnectionUnavailableError instead, and terminalize it: status polls persist failed with the connection error and stop; a pending cancellation persists failed locally because the remote task can no longer be reached. Transient status/cancel errors keep their existing capped-backoff retry policy.

Tests: new service tests pin both terminal paths, and caller tests pin the exception for missing deployment and stale personal server names.

* fix(mcp): preserve LookupError compatibility for connection errors

McpTaskConnectionUnavailableError now subclasses LookupError instead of RuntimeError. The four existing personal-MCP assertions in test_personal_mcp.py still treat a missing or stale connection as a lookup failure; keeping that base preserves their behavior and avoids breaking callers that caught the previous type, while the task service still catches this exact type for permanent-failure classification.

Add a compatibility test and rerun the personal-MCP and task suites.

---------

Co-authored-by: Tong-bit-art <Tong-bit-art@users.noreply.github.com>
2026-10-19 11:32:28 +08:00

35 lines
856 B
Python

from deerflow.mcp.tasks.driver import McpTaskDriver, McpTaskDriverRegistry
from deerflow.mcp.tasks.models import (
ATTENTION_TASK_STATUSES,
POLLABLE_TASK_STATUSES,
TERMINAL_TASK_STATUSES,
TaskReference,
TaskSnapshot,
TaskStatus,
TaskSubmission,
TaskSubmitRequest,
)
from deerflow.mcp.tasks.ordinary import (
ORDINARY_MCP_TASK_DRIVER,
McpTaskConnectionUnavailableError,
McpTaskProtocolError,
OrdinaryMcpTaskDriver,
)
__all__ = [
"ATTENTION_TASK_STATUSES",
"McpTaskDriver",
"McpTaskDriverRegistry",
"POLLABLE_TASK_STATUSES",
"TERMINAL_TASK_STATUSES",
"TaskReference",
"TaskSnapshot",
"TaskStatus",
"TaskSubmission",
"TaskSubmitRequest",
"ORDINARY_MCP_TASK_DRIVER",
"McpTaskConnectionUnavailableError",
"McpTaskProtocolError",
"OrdinaryMcpTaskDriver",
]