Fix task result serialization for SDK v2 (ISO createdAt, drop ServerNotification wrapper)

This commit is contained in:
Jeremiah Lowin 2026-07-05 20:51:40 -04:00
commit e231d51d5e
No known key found for this signature in database
3 changed files with 16 additions and 11 deletions

View file

@ -347,7 +347,9 @@ class ClientToolsMixin:
# Per SEP-1686 final spec: client sends only ttl, server generates taskId
# Inject trace context into meta for propagation to server
propagated_meta = inject_trace_context(meta)
request_meta = cast(mcp_types.RequestParams.Meta | None, propagated_meta)
# SDK v2: request `_meta` is `RequestParamsMeta` (a TypedDict), not the
# old `RequestParams.Meta` nested model.
request_meta = cast(mcp_types.RequestParamsMeta | None, propagated_meta)
# Build request with task metadata
request = mcp_types.CallToolRequest(

View file

@ -77,8 +77,11 @@ async def submit_to_docket(
# Server MUST generate task IDs, clients no longer provide them
server_task_id = str(uuid.uuid4())
# Record creation timestamp per SEP-1686 final spec (line 430)
# Record creation timestamp per SEP-1686 final spec (line 430). SDK v2
# types `Task.created_at` / `TaskStatusNotificationParams.created_at` as ISO
# strings, so carry a serialized copy for wire-crossing models.
created_at = datetime.now(timezone.utc)
created_at_iso = created_at.isoformat()
ctx = get_context()
@ -149,8 +152,8 @@ async def submit_to_docket(
"taskId": server_task_id,
"status": "working",
"statusMessage": "Task submitted",
"createdAt": created_at,
"lastUpdatedAt": created_at,
"createdAt": created_at_iso,
"lastUpdatedAt": created_at_iso,
"ttl": ttl_ms,
"pollInterval": poll_interval_ms,
},
@ -161,10 +164,11 @@ async def submit_to_docket(
},
}
)
server_notification = mcp_types.ServerNotification(notification)
# SDK v2: `ServerNotification` is a union type, not a wrapper class;
# `send_notification` takes the bare notification model directly.
with suppress(Exception):
# Don't let notification failures break task creation
await ctx.session.send_notification(server_notification)
await ctx.session.send_notification(notification) # type: ignore[arg-type] # ty:ignore[invalid-argument-type]
# Queue function to Docket by key (result storage via execution_ttl)
# Use component.add_to_docket() which handles calling conventions
@ -228,8 +232,8 @@ async def submit_to_docket(
task=mcp_types.Task(
task_id=server_task_id,
status="working",
created_at=created_at,
last_updated_at=created_at,
created_at=created_at_iso,
last_updated_at=created_at_iso,
ttl=ttl_ms,
poll_interval=poll_interval_ms,
)

View file

@ -193,9 +193,8 @@ async def _send_mcp_notification(
"_meta": notification_dict.get("_meta"),
}
)
server_notification = mcp_types.ServerNotification(notification)
await session.send_notification(server_notification)
# SDK v2: `ServerNotification` is a union type; send the bare model.
await session.send_notification(notification) # type: ignore[arg-type] # ty:ignore[invalid-argument-type]
# If this is an input_required notification with elicitation metadata,
# relay the elicitation to the client via standard elicitation/create