Documentation
¶
Overview ¶
Package tasks implements the official MCP tasks extension io.modelcontextprotocol/tasks (draft): task-augmented tool execution with polling, input_required rendezvous and status notifications.
Server side: Install the extension, then register long-running tools with AddTool. Client side: declare the capability via client Options.Extensions, detect task creation with AsTask, and follow the task with Await.
Index ¶
- Constants
- Variables
- func AddTool[In any](t *Tasks, tool *protocol.Tool, handler HandlerFor[In])
- func Cancel(ctx context.Context, c Caller, taskID string) error
- func EnableClient(opts *client.Options)
- func Update(ctx context.Context, c Caller, taskID string, ...) error
- type Caller
- type CancelParams
- type Capability
- type Context
- type DetailedTask
- type GetParams
- type HandlerFor
- type MemStore
- type OnInputFunc
- type Options
- type Status
- type Store
- type Task
- type Tasks
- type UpdateParams
Constants ¶
const ( MethodGet = "tasks/get" MethodUpdate = "tasks/update" MethodCancel = "tasks/cancel" // NotificationTasks is the subscriptions/listen notification method; its // params are a full DetailedTask. NotificationTasks = "notifications/tasks" // FilterTaskIDs is the subscriptions/listen filter field selecting task // status notifications. FilterTaskIDs = "taskIds" // ResultTypeTask marks a tools/call result that created a task. ResultTypeTask = "task" )
const ID = "io.modelcontextprotocol/tasks"
ID is the extension identifier, declared in capabilities.extensions on both sides.
Variables ¶
var ErrNotFound = errors.New("tasks: task not found")
ErrNotFound is returned by Store.Get for unknown (or expired) task IDs.
var RouteNames = map[string]string{
MethodGet: "taskId",
MethodUpdate: "taskId",
MethodCancel: "taskId",
}
RouteNames maps the extension's methods to the params key sent as the Mcp-Name routing header, as the draft requires over Streamable HTTP.
Functions ¶
func AddTool ¶
func AddTool[In any](t *Tasks, tool *protocol.Tool, handler HandlerFor[In])
AddTool registers a task-capable tool. Clients that declare the tasks capability on the request receive a CreateTaskResult immediately and follow the task via tasks/get; clients without it get the tool executed synchronously (or rejected, per Options.Reject).
func EnableClient ¶
EnableClient configures opts to declare the tasks capability and emit the extension's routing headers. Call it before client.New:
opts := &client.Options{...}
tasks.EnableClient(opts)
c := client.New(transport, opts)
Types ¶
type CancelParams ¶
type CancelParams struct {
TaskID string `json:"taskId"`
}
type Capability ¶
type Capability struct{}
Capability is the value to declare under client Options.Extensions[ID].
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context provides task facilities to a running handler.
func (*Context) Interactive ¶
Interactive reports whether the handler runs as a task and can use RequireInput.
func (*Context) RequireInput ¶
func (c *Context) RequireInput(ctx context.Context, requests protocol.InputRequests) (protocol.InputResponses, error)
RequireInput parks the task in input_required and blocks until the client has answered every request via tasks/update (partial submissions merge; the task stays input_required with the remaining subset outstanding) or ctx ends. In synchronous fallback mode it fails immediately; tools that cannot proceed without input should be installed with Options.Reject.
type DetailedTask ¶
type DetailedTask struct {
Task
// InputRequests is set while Status is input_required.
InputRequests protocol.InputRequests `json:"inputRequests,omitempty"`
// Result is the stored tool result (including resultType) once completed.
Result json.RawMessage `json:"result,omitempty"`
// Error is set once failed.
Error *protocol.Error `json:"error,omitempty"`
}
DetailedTask adds the status-dependent fields. It is the tasks/get result (a plain complete result) and the notifications/tasks payload.
func Await ¶
func Await(ctx context.Context, c Caller, task *Task, onInput OnInputFunc) (*DetailedTask, error)
Await polls the task until it reaches a terminal status, honoring the server's pollIntervalMs. When the task requires input and onInput is non-nil, Await answers via tasks/update and keeps waiting; with a nil onInput an input_required task is returned as-is.
func TaskEvent ¶
func TaskEvent(ev client.Event) (*DetailedTask, bool)
TaskEvent decodes a notifications/tasks subscription event.
func (*DetailedTask) ResultType ¶
func (*DetailedTask) ResultType() string
func (*DetailedTask) ToolResult ¶
func (d *DetailedTask) ToolResult() (*protocol.CallToolResult, error)
ToolResult decodes a completed task's stored tools/call result.
type HandlerFor ¶
type HandlerFor[In any] func(ctx context.Context, tc *Context, in In) (*protocol.CallToolResult, error)
HandlerFor is a task-capable tool handler. ctx is the task's own lifetime (cancelled by tasks/cancel), not the creating request's. In synchronous fallback mode ctx is the original request context and tc is non-interactive.
type MemStore ¶
type MemStore struct {
// contains filtered or unexported fields
}
MemStore is the in-process Store. Tasks expire TTLMs after their last update; expired entries are evicted lazily.
func NewMemStore ¶
func NewMemStore() *MemStore
type OnInputFunc ¶
type OnInputFunc func(ctx context.Context, requests protocol.InputRequests) (protocol.InputResponses, error)
OnInputFunc answers a task's outstanding input requests during Await.
type Options ¶
type Options struct {
// PollIntervalMs is advertised on every task (default 500).
PollIntervalMs int64
// TTL is how long finished tasks stay retrievable (default 5 minutes).
TTL time.Duration
// Reject makes task tools fail with -32021 for clients that did not
// declare the tasks capability on the request, instead of falling back to
// synchronous execution.
Reject bool
}
type Store ¶
type Store interface {
// Put creates or replaces a task snapshot.
Put(ctx context.Context, t *DetailedTask) error
// Get returns a copy of the task, or ErrNotFound.
Get(ctx context.Context, taskID string) (*DetailedTask, error)
// Delete removes a task; deleting an unknown task is not an error.
Delete(ctx context.Context, taskID string) error
}
Store persists task snapshots. Implementations must be safe for concurrent use. An external store makes task state visible across server instances; note that the input_required rendezvous (tasks/update waking a blocked handler) is in-memory, so multi-instance deployments need sticky routing for interactive tasks.
type Task ¶
type Task struct {
protocol.WithMeta
TaskID string `json:"taskId"`
Status Status `json:"status"`
StatusMessage string `json:"statusMessage,omitempty"`
CreatedAt string `json:"createdAt"`
LastUpdatedAt string `json:"lastUpdatedAt"`
// TTLMs is how long the server retains the task; null means indefinitely.
// The field is required on the wire.
TTLMs *int64 `json:"ttlMs"`
PollIntervalMs int64 `json:"pollIntervalMs,omitempty"`
}
Task is the base task object. Returned from tools/call it is the CreateTaskResult (resultType "task").
func AsTask ¶
AsTask inspects a CallTool error: when the server turned the call into a task (resultType "task"), it returns the CreateTaskResult.
func (*Task) ResultType ¶
type Tasks ¶
type Tasks struct {
// contains filtered or unexported fields
}
Tasks is the installed extension; AddTool registers task-capable tools against it.
type UpdateParams ¶
type UpdateParams struct {
TaskID string `json:"taskId"`
InputResponses protocol.InputResponses `json:"inputResponses"`
}