Repository navigation
feat(tasks): serve the MCP Tasks extension - #35
Merged
Merged
Conversation
dbernheisel
force-pushed
the
ext-tasks
branch
2 times, most recently
from
October 4, 2026 23:33
2cef5f6 to
1e4b64f
Compare
A tool answers tools/call with a task by returning
{:reply, %Phantom.Tasks{}, session}. Phantom does not store tasks: the
router implements get_task/2 (and optionally update_task/3,
cancel_task/2, authorize_task_subscriptions/2) for tasks/get,
tasks/update, and tasks/cancel under MCP 2026-07-28.
Phantom.Tracker.notify_task_updated/1 sends notifications/tasks to
subscriptions/listen streams, which fetch the task with get_task/2.
The conformance suite's tasks scenarios now run and must pass. A guide
covers storing and running tasks with Ecto, Oban, and Oban Pro.
dbernheisel
marked this pull request as ready for review
October 5, 2026 00:55
The formatter output differs between Elixir versions, so only the newest version in the matrix checks it.
The suite's summary names only the scenario, which is not enough to diagnose a failure that occurs only in CI.
A response to a server-initiated request, such as elicitation/create, could reach a node whose Phantom.Tracker had not yet replicated the waiting request. The lookup gave up after 2 seconds and dropped the response, so the elicitation hung. The waiting session process now subscribes to a topic for the request, and the response is broadcast to it. The Tracker lookup remains for servers without PubSub.
The most specific matching media range decides, as RFC 9110 specifies, so "*/*;q=0.5, text/event-stream;q=0" refuses the stream.
A client can send logging/setLevel or resources/subscribe before its GET stream subscribes on another node. The single broadcast reached no stream, so the call failed with "Connection closed" or "SSE stream not open". The call now repeats with backoff until a stream answers or the timeout passes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phantom.Tasks. A tool returns{:reply, %Phantom.Tasks{}, session}to answertools/callwith a task (lib/phantom/tasks.ex,Router.finalize_result/5).get_task/2to enable the extension.update_task/3,cancel_task/2, andauthorize_task_subscriptions/2are optional (lib/phantom/router.ex).tasks/get,tasks/update, andtasks/cancelunder MCP 2026-07-28. Return -32021 when the request does not declare the extension, -32602 for an unknown task, and -32601 when the router does not implement tasks.Mcp-Nameto equaltaskIdontasks/*(lib/phantom/plug.ex).taskIdsonsubscriptions/listen.Phantom.Tracker.notify_task_updated/1sendsnotifications/tasks. Each stream fetches the task withget_task/2before it sends, and stops following a finished task.Phantom.Session.tasks_supported?/1,Phantom.Request.missing_task_capability/0,Phantom.Elicit.to_input_request/1, andPhantom.Testtask helpers.Phantom.Session.progress_ref/1. It gives a JSON-safe reference to the current request. A job on any node sends progress withPhantom.Session.notify_progress/4. The request stream subscribes to a PubSub topic for the request before the handler runs.guides/tasks.mdwith examples for Ecto, Oban, and Oban Pro.taskIds, a capability check on taskinputRequests, and removal of the duplicated fail-closed and notification blocks that the resource code also has.Evidence
Run with
MIX_ENV=test iex -S mix. The conformance router runs over Bandit. Req sends the requests over HTTP. The first task asks for input, gets it, and completes. The second task is cancelled while it works.iex
Conformance:
mix test test/conformance/conformance_test.exs --include conformancepasses 30 of 30, which includes the 10 tasks scenarios on both topologies.