diff --git a/.gitignore b/.gitignore index ead45c0..1ea2b7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules/ -package-lock.json .DS_Store .idea/ .vscode/ diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..8feffe4 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,207 @@ +--- +title: Overview +group: Getting Started +description: MCP Tasks lets servers return durable poll handles instead of blocking on long-running tool calls. Clients poll for progress, provide mid-flight input, and retrieve results after reconnecting. +--- + +# MCP Tasks Overview + +MCP Tasks is an extension to the Model Context Protocol. Servers return a durable task handle instead of blocking on a long-running operation; clients poll for progress and retrieve the result when ready. + +**Extension Identifier:** `io.modelcontextprotocol/tasks` + +## Why Tasks? + +Tool calls block until work finishes. Tasks solve the cases where blocking is impractical: + +- **CI pipelines and batch jobs** — minutes or hours of execution +- **Human-in-the-loop workflows** — approval gates that block until a person responds +- **External job systems** — cloud deployments, queued work, async APIs with their own job IDs +- **Unreliable connections** — mobile clients, intermittent networks, transport intermediary timeouts + +A task ID is a durable handle that survives disconnects and carries status metadata, without requiring long-lived connections or unsolicited server-to-client messages. + +## Progressive Enhancement + +Servers only return task handles to clients that declared the extension in their per-request capabilities — otherwise, the server either blocks for a regular result as usual or returns a capability error. + +A server that requires task support from the client for a given request returns a `-32003` (Missing Required Client Capability) error, like so: + +```jsonc +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + // MISSING_REQUIRED_CLIENT_CAPABILITY + "code": -32003, + "message": "Missing required client capability", + "data": { + "requiredCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {} + } + } + } + } +} +``` + +## Architecture + +```mermaid +flowchart LR + subgraph Client ["MCP Client"] + P[Poll Loop] + I[Input Handler] + end + + subgraph Server ["MCP Server"] + T[Task Store] + W[Worker] + end + + Client -->|"tools/call"| Server + Server -->|"CreateTaskResult"| Client + P -->|"tasks/get"| T + T -->|"DetailedTask"| P + I -->|"tasks/update"| T + W --> T +``` + +- **Client** — Drives all interaction: issues tool calls, polls for completion, and fulfills input requests. +- **Server** — Decides per-request whether to create a task and manages task state durably. +- **Task Store** — Durable state reachable by `tasks/get` even if the worker or connection has died. A `CreateTaskResult` is not returned until the task is findable here. +- **Worker** — The computation backing the task. Updates the task store as it progresses and writes the final result or error on completion. + +## Lifecycle + +```mermaid +sequenceDiagram + participant Client + participant Server + + Note over Client,Server: 1. Capability Negotiation + Client->>Server: tools/call (with io.modelcontextprotocol/tasks capability) + + Note over Client,Server: 2. Task Creation + Server-->>Client: CreateTaskResult (taskId, status: working) + + Note over Client,Server: 3. Polling + loop Poll until terminal + Client->>Server: tasks/get (taskId) + Server-->>Client: Task (status: working) + end + + Note over Client,Server: 4. Mid-flight Input + Client->>Server: tasks/get (taskId) + Server-->>Client: Task (status: input_required, inputRequests) + Client->>Server: tasks/update (taskId, inputResponses) + Server-->>Client: ack + + Note over Client,Server: 5. Completion + loop Poll until terminal + Client->>Server: tasks/get (taskId) + Server-->>Client: Task (status: working) + end + Client->>Server: tasks/get (taskId) + Server-->>Client: Task (status: completed, result) +``` + +1. **Capability negotiation** — The client includes `io.modelcontextprotocol/tasks` in `_meta.io.modelcontextprotocol/clientCapabilities.extensions`. The server advertises the same in `server/discover`. No per-tool warmup or per-request flag. + +2. **Task creation** — The server returns a `CreateTaskResult` with `resultType: "task"`, containing a `taskId`, initial status, TTL, and polling interval. The task is durably created before the response is sent. + +3. **Polling** — The client calls `tasks/get` with the `taskId`, respecting `pollIntervalMs`, until the task reaches a terminal status (which includes the final result or error). + +4. **Mid-flight input** — If the task moves to `input_required`, `tasks/get` includes an `inputRequests` map that the client fulfills via `tasks/update`, after which the task transitions back to `working`. + +5. **Completion** — `completed`: `result` contains what the original request would have returned synchronously. `failed`: `error` contains the JSON-RPC error. + +## Task Status + +```mermaid +stateDiagram-v2 + [*] --> working + working --> input_required + working --> completed + working --> failed + working --> cancelled + input_required --> working + input_required --> completed + input_required --> failed + input_required --> cancelled + completed --> [*] + failed --> [*] + cancelled --> [*] +``` + +| Status | Meaning | +| ---------------- | -------------------------------------------------------------------------- | +| `working` | The operation is in progress. | +| `input_required` | The server needs client input before continuing. See `inputRequests`. | +| `completed` | The operation finished. `result` contains the final output. | +| `failed` | A JSON-RPC error occurred during execution. `error` has details. | +| `cancelled` | The operation was cancelled (not always honored). | + +`completed`, `failed`, and `cancelled` are terminal. + +Each task also carries: + +- **`statusMessage`** — Optional description of current state +- **`createdAt` / `lastUpdatedAt`** — ISO 8601 timestamps +- **`ttlMs`** — Time-to-live from creation in milliseconds; may change over lifetime; `null` for unlimited +- **`pollIntervalMs`** — Suggested polling interval; may change over lifetime + +## Mid-flight Input + +When a task needs client input, it transitions to `input_required` and the `tasks/get` response includes an `inputRequests` map. The client fulfills these via `tasks/update`, which returns an empty ack: + +```json +{ + "status": "input_required", + "inputRequests": { + "approval": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Approve deployment to production?", + "requestedSchema": { + "type": "object", + "properties": { "approved": { "type": "boolean" } }, + "required": ["approved"] + } + } + } + } +} +``` + +Each key in `inputRequests` is unique over the lifetime of a task. The server may accept partial responses; the task remains `input_required` until all arrive. Reads (`tasks/get`) and writes (`tasks/update`) are separate to keep reads idempotent and cacheable. + +See the [specification](./specification/draft/tasks.mdx) for the full `tasks/update` request shape and consistency semantics. + +## Cancellation and Notifications + +Clients send `tasks/cancel` to signal cancellation intent. The server acks with an empty result — cancellation is cooperative, and the task may still reach a non-`cancelled` terminal status. + +Servers may also push status updates via `notifications/tasks`, which clients opt into through `subscriptions/listen`. Each notification carries the full task state, identical to a `tasks/get` response. + +See the [specification](./specification/draft/tasks.mdx) for details on both mechanisms. + +## Security + +- **Task ID unguessability.** Task IDs are generated with sufficient entropy to prevent enumeration, and may serve as bearer tokens for stored state. +- **No task enumeration.** There is no `tasks/list`, so one caller's tasks are not visible to another. +- **Input-request trust model.** `inputRequests` carry elicitation/sampling payloads from server to client. Hosts apply the same trust model as for standard elicitation/sampling requests. + +## Supported Methods + +Task-augmented execution is currently supported for: + +- `tools/call` + +## Learn More + +- [Specification](./specification/draft/tasks.mdx) — Full protocol specification +- [SEP-2663](../seps/2663-tasks-extension.md) — The proposal defining this extension +- [Schema](../schema/) — TypeScript types and generated JSON Schema diff --git a/docs/specification/draft/tasks.mdx b/docs/specification/draft/tasks.mdx index ae31d3d..aa73a28 100644 --- a/docs/specification/draft/tasks.mdx +++ b/docs/specification/draft/tasks.mdx @@ -6,58 +6,77 @@ title: Tasks -**This document is part of the experimental Tasks extension (`io.modelcontextprotocol/tasks`).** +**This document is part of the Tasks extension (`io.modelcontextprotocol/tasks`).** -Tasks were introduced in version 2025-11-25 of the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25) -and are currently considered **experimental**. The design and behavior of tasks may evolve in future versions. +This extension allows a server to respond to a `tools/call` request with an asynchronous _task handle_ instead of a final result, allowing the client to retrieve the eventual result by polling. The extension introduces three methods: `tasks/get`, `tasks/update`, and `tasks/cancel`; a polymorphic-result discriminator (`resultType: "task"`); and a `Task` shape that carries a task status, in-progress server-to-client requests, and a final result or error. -This content is extracted from the core specification to support the extension's incubation. -For the core protocol specification, see [modelcontextprotocol.io](https://modelcontextprotocol.io/specification/2025-11-25). +Task creation is server-directed: the client signals support by including the extension in its per-request capabilities, and the server decides on a per-request basis whether to materialize a task. -The Model Context Protocol (MCP) allows requestors — which can be either clients or servers, depending on the direction of communication — to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. +The Model Context Protocol (MCP) Tasks extension allows certain requests to be augmented with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they augment, and are intended for client polling and deferred result retrieval. Each task is uniquely identifiable by a server-generated **task ID**. -Tasks are useful for representing expensive computations and batch processing requests, and integrate seamlessly with external job APIs. +Tasks are useful for representing expensive computations and batch processing requests, and map naturally onto external job APIs. -## Definitions +## Extension Identifier -Tasks represent parties as either "requestors" or "receivers," defined as follows: +This extension is identified as: `io.modelcontextprotocol/tasks`. -- **Requestor:** The sender of a task-augmented request. This can be the client or the server — either can create tasks. -- **Receiver:** The receiver of a task-augmented request, and the entity executing the task. This can be the client or the server — either can receive and execute tasks. +## Capability Negotiation -## User Interaction Model +The client and server declare support for the tasks extension in their respective capabilities objects: -Tasks are designed to be **requestor-driven** - requestors are responsible for augmenting requests with tasks and for polling for the results of those tasks; meanwhile, receivers tightly control which requests (if any) support task-based execution and manages the lifecycles of those tasks. - -This requestor-driven approach ensures deterministic response handling and enables sophisticated patterns such as dispatching concurrent requests, which only the requestor has sufficient context to orchestrate. - -Implementations are free to expose tasks through any interface pattern that suits their needs — the protocol itself does not mandate any specific user interaction model. +```jsonc +// Client to server, in per-request capabilities +{ + // Other request parameters... + "params": { + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, + }, +} +``` -## Capabilities +```jsonc +// Server to client, in response to server/discover +{ + "result": { + // Other response parameters... + "capabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, +} +``` -Servers and clients that support task-augmented requests **MUST** declare a `tasks` capability during initialization. The `tasks` capability is structured by request category, with boolean properties indicating which specific request types support task augmentation. +No extension-specific settings are currently defined; an empty object indicates support. -### Server Capabilities +A server that has negotiated this extension **MAY** return `CreateTaskResult` in lieu of a standard result (e.g. `CallToolResult`) in response to any supported request at its own discretion and on a per-request basis. The server is the sole decider; clients do not signal task preference on the request itself. The client declaring the extension capability does not suggest that it requires a `CreateTaskResult` in response to that request. -Servers declare if they support tasks, and if so, which server-side requests can be augmented with tasks. +A server **MUST NOT** return `CreateTaskResult` to a client that did not include the extension capability on its request, regardless of prior declarations. A client that has negotiated this extension **MUST** be prepared to handle either `CallToolResult` or `CreateTaskResult` in response to any supported request it issues. A client that receives `CreateTaskResult` in response to an unsupported request type **MUST** interpret this as an invalid response to the request. -| Capability | Description | -| --------------------------- | ---------------------------------------------------- | -| `tasks.list` | Server supports the `tasks/list` operation | -| `tasks.cancel` | Server supports the `tasks/cancel` operation | -| `tasks.requests.tools.call` | Server supports task-augmented `tools/call` requests | +If a server is unable to service a request to a client that does not declare this extension capability without returning `CreateTaskResult`, the server **MUST** return an error with the code `-32003` (Missing Required Client Capability), indicating the required extension in the error response: -```json +```jsonl { - "capabilities": { - "tasks": { - "list": {}, - "cancel": {}, - "requests": { - "tools": { - "call": {} + "jsonrpc": "2.0", + "id": 1, + "error": { + // MISSING_REQUIRED_CLIENT_CAPABILITY + "code": -32003, + // Message provided for example purposes only. The content of this example message is non-normative. + "message": "Missing required client capability", + "data": { + "requiredCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {} } } } @@ -65,74 +84,185 @@ Servers declare if they support tasks, and if so, which server-side requests can } ``` -### Client Capabilities +## Supported Methods -Clients declare if they support tasks, and if so, which client-side requests can be augmented with tasks. +The following methods currently support task-augmented execution: -| Capability | Description | -| --------------------------------------- | ---------------------------------------------------------------- | -| `tasks.list` | Client supports the `tasks/list` operation | -| `tasks.cancel` | Client supports the `tasks/cancel` operation | -| `tasks.requests.sampling.createMessage` | Client supports task-augmented `sampling/createMessage` requests | -| `tasks.requests.elicitation.create` | Client supports task-augmented `elicitation/create` requests | +- `tools/call` -```json -{ - "capabilities": { - "tasks": { - "list": {}, - "cancel": {}, - "requests": { - "sampling": { - "createMessage": {} - }, - "elicitation": { - "create": {} - } - } - } - } +This specification may be extended to support tasks over other request types in the future; implementations **SHOULD** be designed to accommodate additional request types in future revisions of this specification. + +## Polymorphic Results + +A request that is eligible for task-augmentation may return one of two distinct result shapes — the request's standard result, or a `CreateTaskResult`. The discriminator is the `resultType` field on the result object: + +```typescript +// "task" is introduced by this extension. +type ResultType = "complete" | "input_required" | "task"; +``` + +Servers **MUST** set `resultType` to `"task"` when returning a `CreateTaskResult` so that clients can distinguish it from a standard result. Servers **MUST NOT** set `resultType` to `"task"` on result types other than `CreateTaskResult`. + +## Tasks + +A `Task` carries operational metadata about ongoing work. + +```typescript +interface Task { + /** Stable identifier for this task. */ + taskId: string; + + /** Current task status. */ + status: "working" | "input_required" | "completed" | "cancelled" | "failed"; + + /** + * Optional message describing the current task state. + * This can provide context for any status, for example (non-normative): + * - Progress descriptions for "working" + * - Work blocked on "input_required" + * - Reasons for "cancelled" status + * - Summaries for "completed" status + * - Additional information for "failed" status (e.g., error details, what went wrong) + * + * This MAY be exposed to the end-user or model. + */ + statusMessage?: string; + + /** ISO 8601 timestamp when the task was created. */ + createdAt: string; + + /** ISO 8601 timestamp when the task was last updated. */ + lastUpdatedAt: string; + + /** + * Time-to-live duration from creation in integer milliseconds, null for unlimited. + * The server may discard the task after the TTL elapses. This value MAY change + * over the lifetime of a task. + */ + ttlMs: number | null; + + /** + * Suggested polling interval in integer milliseconds. Clients SHOULD honor + * this value to avoid overwhelming the server. This value MAY change over + * the lifetime of a task. + */ + pollIntervalMs?: number; } ``` -### Capability Negotiation +### Task Status -During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **SHOULD** only augment requests with a task if the corresponding capability has been declared by the receiver. +Tasks can be in one of the following states: -For example, if a server's capabilities include `tasks.requests.tools.call: {}`, then clients may augment `tools/call` requests with a task. If a client's capabilities include `tasks.requests.sampling.createMessage: {}`, then servers may augment `sampling/createMessage` requests with a task. +- `working`: The request is currently being processed. +- `input_required`: The server needs input from the client. The `tasks/get` response will include outstanding requests in the `inputRequests` field, and the client should provide responses via the `inputResponses` field in subsequent `tasks/update` requests. +- `completed`: The request completed successfully and results are available in the `result` field. This includes tool calls that returned results with `isError: true`. +- `failed`: The request failed due to a JSON-RPC error during execution. The task will include the `error` field with the JSON-RPC error details. This status **MUST NOT** be used for non-JSON-RPC errors. +- `cancelled`: The request was cancelled before completion. -If `capabilities.tasks` is not defined, the peer **SHOULD NOT** attempt to create tasks during requests. +Derived shapes of `Task` inline status-specific payload fields and are used by `tasks/get` responses and `notifications/tasks` notifications: -The set of capabilities in `capabilities.tasks.requests` is exhaustive. If a request type is not present, it does not support task-augmentation. +```ts +/** + * A task that is in a normal working state. + * Used by tasks/get and notifications/tasks. + */ +export interface WorkingTask extends Task { + status: "working"; +} -`capabilities.tasks.list` controls if the `tasks/list` operation is supported by the party. +/** + * A task that is waiting for input from the client. + * Used by tasks/get and notifications/tasks. + */ +export interface InputRequiredTask extends Task { + status: "input_required"; + /** + * Server-to-client requests that need to be fulfilled during task execution. + * Keys are arbitrary identifiers for matching requests to responses. + */ + inputRequests: InputRequests; +} -`capabilities.tasks.cancel` controls if the `tasks/cancel` operation is supported by the party. +/** + * A task that has completed successfully. + * Used by tasks/get and notifications/tasks. + */ +export interface CompletedTask extends Task { + status: "completed"; + /** + * The final result of the task. + * The structure matches the result type of the original request. + * For example, a CallToolRequest task would return the CallToolResult structure. + */ + result: JSONObject; +} -### Tool-Level Negotiation +/** + * A task that has failed due to a JSON-RPC error. + * Used by tasks/get and notifications/tasks. + */ +export interface FailedTask extends Task { + status: "failed"; + /** + * The JSON-RPC error that caused the task to fail. + */ + error: JSONObject; +} -Tool calls are given special consideration for the purpose of task augmentation. In the result of `tools/list`, tools declare support for tasks via `execution.taskSupport`, which if present can have a value of `"required"`, `"optional"`, or `"forbidden"`. +/** + * A task that has been cancelled. + * Used by tasks/get and notifications/tasks. + */ +export interface CancelledTask extends Task { + status: "cancelled"; +} -This is to be interpreted as a fine-grained layer in addition to capabilities, following these rules: +/** + * A union type representing a task with optional inlined result/error/inputRequests fields. + * This type is used by tasks/get and notifications/tasks to provide complete task state + * including terminal results or pending input requests. + */ +export type DetailedTask = + | WorkingTask + | InputRequiredTask + | CompletedTask + | FailedTask + | CancelledTask; +``` -1. If a server's capabilities do not include `tasks.requests.tools.call`, then clients **MUST NOT** attempt to use task augmentation on that server's tools, regardless of the `execution.taskSupport` value. -1. If a server's capabilities include `tasks.requests.tools.call`, then clients consider the value of `execution.taskSupport`, and handle it accordingly: - 1. If `execution.taskSupport` is not present or `"forbidden"`, clients **MUST NOT** attempt to invoke the tool as a task. Servers **SHOULD** return a `-32601` (Method not found) error if a client attempts to do so. This is the default behavior. - 1. If `execution.taskSupport` is `"optional"`, clients **MAY** invoke the tool as a task or as a normal request. - 1. If `execution.taskSupport` is `"required"`, clients **MUST** invoke the tool as a task. Servers **MUST** return a `-32601` (Method not found) error if a client does not attempt to do so. +**Task Status State Diagram:** -## Protocol Messages +```mermaid +stateDiagram-v2 + [*] --> working -### Creating Tasks + working --> input_required + working --> terminal -Task-augmented requests follow a two-phase response pattern that differs from normal requests: + input_required --> working + input_required --> terminal + + terminal --> [*] + + note right of terminal + Terminal states: + - completed + - failed + - cancelled + end note +``` -- **Normal requests**: The server processes the request and returns the actual operation result directly. -- **Task-augmented requests**: The server accepts the request and immediately returns a `CreateTaskResult` containing task data. The actual operation result becomes available later through `tasks/result` after the task completes. +## Task Creation -To create a task, requestors send a request with the `task` field included in the request params. Requestors **MAY** include a `ttl` value indicating the desired task lifetime duration (in milliseconds) since its creation. +A server returns `CreateTaskResult` in lieu of the standard result shape for a request to indicate that request will be processed asynchronously. -**Request:** +```typescript +// resultType: "task" +type CreateTaskResult = Result & Task; +``` + +**Example Request (CallToolRequest):** ```json { @@ -143,656 +273,533 @@ To create a task, requestors send a request with the `task` field included in th "name": "get_weather", "arguments": { "city": "New York" - }, - "task": { - "ttl": 60000 } } } ``` -**Response:** +**Example Response (CreateTaskResult):** ```json { "jsonrpc": "2.0", "id": 1, "result": { - "task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "working", - "statusMessage": "The operation is now in progress.", - "createdAt": "2025-11-25T10:30:00Z", - "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 60000, - "pollInterval": 5000 - } + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "statusMessage": "The operation is now in progress.", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:40:00Z", + "ttlMs": 60000, + "pollIntervalMs": 5000 } } ``` -When a receiver accepts a task-augmented request, it returns a [`CreateTaskResult`](https://modelcontextprotocol.io/specification/2025-11-25/schema#createtaskresult) containing task data. The response does not include the actual operation result. The actual result (e.g., tool result for `tools/call`) becomes available only through `tasks/result` after the task completes. +The embedded `task` is the seed state for the task, typically (though not necessarily) with `status: "working"`. The client uses `task.taskId` for all subsequent `tasks/get`, `tasks/update`, and `tasks/cancel` calls. - +A server **MUST NOT** return `CreateTaskResult` until the task is durably created — that is, until a `tasks/get` for the returned `taskId` would resolve. In eventually-consistent environments, the server **MUST** wait for consistency before responding. This requirement eliminates the need for clients to speculatively poll for task creation. -When a task is created in response to a `tools/call` request, host applications may wish to return control to the model while the task is executing. This allows the model to continue processing other requests or perform additional work while waiting for the task to complete. +Server implementations that use multi round-trip requests in conjunction with task creation (for example, a tool that requires elicitation over `InputRequiredResult` before creating a task) **SHOULD** resolve all MRTR exchanges _synchronously_ before responding with a `CreateTaskResult`. -To support this pattern, servers can provide an optional `io.modelcontextprotocol/model-immediate-response` key in the `_meta` field of the `CreateTaskResult`. The value of this key should be a string intended to be passed as an immediate tool result to the model. -If a server does not provide this field, the host application can fall back to its own predefined message. +## Task Polling -This guidance is non-binding and is provisional logic intended to account for the specific use case. This behavior may be formalized or modified as part of `CreateTaskResult` in future protocol versions. +Clients poll for task completion by sending `tasks/get` requests. - +Clients **SHOULD** respect the `pollIntervalMs` provided in responses when determining polling frequency. The `pollIntervalMs` **MAY** change over the lifetime of a task. Servers **MAY** rate-limit clients polling more frequently than the recorded `pollIntervalMs`. -### Getting Tasks +Clients **SHOULD** continue polling until the task reaches a terminal status or until invoking `tasks/cancel`. Clients **SHOULD** persist task IDs to durable storage so that polling can resume after a crash or restart. - +### Request -In the Streamable HTTP (SSE) transport, clients **MAY** disconnect from an SSE stream opened by the server in response to a `tasks/get` request at any time. +```typescript +interface GetTaskRequest extends JSONRPCRequest { + method: "tasks/get"; + params: { + /** Identifier of the task to query. */ + taskId: string; + }; +} +``` -While this note is not prescriptive regarding the specific usage of SSE streams, all implementations **MUST** continue to comply with the existing [Streamable HTTP transport specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server). +### Response - +Upon receiving a `tasks/get` request, the server **MUST** check the status of the task and respond accordingly: -Requestors poll for task completion by sending [`tasks/get`](https://modelcontextprotocol.io/specification/2025-11-25/schema#tasks%2Fget)requests. -Requestors **SHOULD** respect the `pollInterval` provided in responses when determining polling frequency. +1. If the status is `working`, the server **MUST** return a a `Task` object with status `working`. +2. If the status is `input_required`, the server **MUST** return a `Task` object with status `input_required` and an `inputRequests` field defined in [Multi Round-Trip Requests](https://modelcontextprotocol.io/specification/draft/basic/utilities/mrtr). The `inputRequests` field **MUST** contain all outstanding requests from the server to the client that need to be fulfilled before the task can proceed. +3. If the status is `completed`, the server **MUST** return a `Task` object with status `completed` and a `result` field containing the final result of the task. +4. If the status is `cancelled`, the server **MUST** return a `Task` object with status `cancelled`. +5. If the status is `failed`, the server **MUST** return a `Task` object with status `failed` and the error that occurred during execution. -Requestors **SHOULD** continue polling until the task reaches a terminal status (`completed`, `failed`, or `cancelled`), or until encountering the [`input_required`](#input-required-status) status. Note that invoking `tasks/result` does not imply that the requestor needs to stop polling - requestors **SHOULD** continue polling the task status via `tasks/get` if they are not actively waiting for `tasks/result` to complete. +```typescript +type GetTaskResult = Result & DetailedTask; +``` -**Request:** +The response carries the appropriate response variant for the task's current status (see [Task Status](#task-status)). The `resultType` field **MUST** be set to `"complete"` on this object as it is the standard result shape for the `tasks/get` request. -```json -{ - "jsonrpc": "2.0", - "id": 3, - "method": "tasks/get", - "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } +If the task has a non-null `ttlMs`, clients **MAY** treat the TTL as a backstop: if the task's observable status has not reflected the update after `createdAt` plus `ttlMs` has elapsed, the client **MAY** consider the task to no longer be usable. Conversely, servers **MAY** mark a task as `failed` at any point after the TTL elapses, and subsequently delete it at any time. The value of `ttlMs` **MAY** change over the lifetime of a task. + +## Task Update Requests + +When a task requires input from the client (indicated by the `input_required` status), the server includes outstanding requests in the `inputRequests` field of the `tasks/get` response (see [Multi Round-Trip Requests](https://modelcontextprotocol.io/specification/draft/basic/utilities/mrtr)). The client provides responses via the `inputResponses` field in one or more subsequent `tasks/update` requests. + +When a client observes a `tasks/get` response (or `notifications/tasks` notification) with `status: "input_required"`, the client **SHOULD** fulfill the outstanding requests in `inputRequests` by sending one or more `tasks/update` requests with corresponding `inputResponses`. After sending a `tasks/update`, the client **SHOULD** continue observing the task's status via polling (`tasks/get`) or notifications (`notifications/tasks`) until it reaches a terminal state. + +Clients **MUST** treat each entry in `inputRequests` as they would the equivalent standalone server-to-client request — for example, an elicitation request surfaced via `inputRequests` is subject to the same trust model and user-facing behavior as a direct `elicitation/create` request. Clients **SHOULD** deduplicate `inputRequests` keys across consecutive polls to avoid presenting the same request to the user or model more than once. + +Each request key in `inputRequests` **MUST** be unique over the lifetime of a single task. A server **MUST NOT** reuse a key for a subsequent server-to-client request after a response for that key has been delivered, and **MUST NOT** use the same key to refer to two distinct requests over a task's lifetime. This guarantees that `inputResponses` keyed by the same identifier always refer to the request the client expects, eliminates ambiguity for clients deduplicating across polls, and lets servers ignore `inputResponses` for unknown or already-satisfied requests. + +### Request + +```typescript +interface UpdateTaskRequest extends JSONRPCRequest { + method: "tasks/update"; + params: { + /** Identifier of the task to update. */ + taskId: string; + + /** + * Responses to outstanding inputRequests previously surfaced by the + * server. Shape per MRTR. Each key MUST correspond to a currently- + * outstanding inputRequest key. + */ + inputResponses: InputResponses; + }; } ``` -**Response:** +### Response -```json -{ - "jsonrpc": "2.0", - "id": 3, - "result": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "working", - "statusMessage": "The operation is now in progress.", - "createdAt": "2025-11-25T10:30:00Z", - "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 30000, - "pollInterval": 5000 - } +```typescript +type UpdateTaskResult = Result; // empty acknowledgement +``` + +On success, the server **MUST** acknowledge the request with an empty result. The acknowledgement is _eventually consistent_: the server **MAY** accept the responses and return the ack before the task's observable status (via `tasks/get` or `notifications/tasks`) reflects them. Servers **SHOULD** return a JSON-RPC error if the `taskId` does not correspond to a known task. Clients **SHOULD** track `inputRequests` keys to avoid responding to requests more than once. + +A server **SHOULD** ignore any `inputResponses` responses mapped to a key that is not currently outstanding for the task — including keys that were never issued, keys that have already been answered, and keys whose corresponding request has been superseded. A server **MAY** accept a partial set of responses (a strict subset of currently-outstanding keys); in that case the task remains in `input_required` until the remaining responses arrive. + +The `resultType` field **MUST** be set to `"complete"` on `UpdateTaskResult` as it is the standard result shape for the `tasks/update` request. + +## Task Cancellation + +A client sends a `tasks/cancel` request to signal its intent to cancel an in-progress task. The `notifications/cancelled` notification **MUST NOT** be used for task cancellation. + +### Request + +```typescript +interface CancelTaskRequest extends JSONRPCRequest { + method: "tasks/cancel"; + params: { + taskId: string; + }; } ``` -### Retrieving Task Results +### Response - +```typescript +type CancelTaskResult = Result; // empty acknowledgement +``` -In the Streamable HTTP (SSE) transport, clients **MAY** disconnect from an SSE stream opened by the server in response to a `tasks/result` request at any time. +On success, the server **MUST** acknowledge the request with an empty result. Servers **SHOULD** return a JSON-RPC error if the `taskId` does not correspond to a known task. Cancellation processing is _eventually consistent_ — the task's observable status **MAY** remain `working` (or some other non-terminal status) after the ack, and **MAY** ultimately reach a terminal status other than `cancelled` if the work finished before cancellation could take effect. -While this note is not prescriptive regarding the specific usage of SSE streams, all implementations **MUST** continue to comply with the existing [Streamable HTTP transport specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server). +Cancellation is **cooperative**: The request signals intent, and the server decides whether and when to honor it. A server is not obligated to actually stop the work; it is only obligated to acknowledge the request. Eventual transition to `cancelled` is not guaranteed. - +Clients **MAY** delete all state associated with the task as soon as they send a cancellation (e.g., it no longer needs to retain the list of `inputRequests` keys that it has already responded to). The client does not need to poll `tasks/get` again to wait for the task to reach the `cancelled` state. -After a task completes the operation result is retrieved via [`tasks/result`](https://modelcontextprotocol.io/specification/2025-11-25/schema#tasks%2Fresult). This is distinct from the initial `CreateTaskResult` response, which contains only task data. The result structure matches the original request type (e.g., `CallToolResult` for `tools/call`). +The `resultType` field **MUST** be set to `"complete"` on `CancelTaskResult` as it is the standard result shape for the `tasks/cancel` request. -To retrieve the result of a completed task, requestors can send a `tasks/result` request: +## Task Status Notifications -While `tasks/result` blocks until the task reaches a terminal status, requestors can continue polling via `tasks/get` in parallel if they are not actively blocked waiting for the result, such as if their previous `tasks/result` request failed or was cancelled. This allows requestors to monitor status changes or display progress updates while the task executes, even after invoking `tasks/result`. +Servers **MAY** push status updates via `notifications/tasks` notifications in addition to servicing client polls: -**Request:** +```typescript +export type TaskStatusNotificationParams = NotificationParams & Task; -```json -{ - "jsonrpc": "2.0", - "id": 4, - "method": "tasks/result", - "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } +export interface TaskStatusNotification extends JSONRPCNotification { + method: "notifications/tasks"; + params: TaskStatusNotificationParams; } ``` -**Response:** +To begin listening for task status notifications, clients send a `subscriptions/listen` request to the server including a list of task IDs the client is interested in: + +```typescript +export interface SubscriptionsListenRequest extends Request { + method: "subscriptions/listen"; + params: { + // Other existing fields... + notifications: { + taskIds?: string[]; + // Other existing fields... + }; + }; +} +``` + +In its acknowledgement notification, the server includes the list of task IDs it has agreed to send task status notifications for, if any: + +```typescript +export interface SubscriptionsAcknowledgedNotification extends Notification { + method: "notifications/subscriptions/acknowledged"; + params: { + notifications: { + /** + * Subscribe to notifications/tasks for specific task IDs. + */ + taskIds?: string[]; + // Other existing fields... + }; + }; +} +``` + +If a client requests task status notifications but does not declare the `io.modelcontextprotocol/tasks` extension capability, the server **MUST** return a JSON-RPC error specifying the missing capabilities: ```json { "jsonrpc": "2.0", - "id": 4, - "result": { - "content": [ - { - "type": "text", - "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" - } - ], - "isError": false, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + "id": 12, + "error": { + "code": -32003, + "message": "Missing required client capability", + "data": { + "requiredCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {} + } } } } } ``` -### Task Status Notification - -When a task status changes, receivers **MAY** send a [`notifications/tasks/status`](https://modelcontextprotocol.io/specification/2025-11-25/schema#notifications%2Ftasks%2Fstatus) notification to inform the requestor of the change. This notification includes the full task state. +Each notification carries a complete `DetailedTask` for the current status, identical to what `tasks/get` would have returned at that moment. **Notification:** ```json { "jsonrpc": "2.0", - "method": "notifications/tasks/status", + "method": "notifications/tasks", "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "completed", "createdAt": "2025-11-25T10:30:00Z", "lastUpdatedAt": "2025-11-25T10:50:00Z", - "ttl": 60000, - "pollInterval": 5000 + "ttlMs": 60000, + "pollIntervalMs": 5000, + "result": { + "content": [ + { + "type": "text", + "text": "Operation completed successfully." + } + ], + "isError": false + } } } ``` -The notification includes the full [`Task`](https://modelcontextprotocol.io/specification/2025-11-25/schema#task) object, including the updated `status` and `statusMessage` (if present). This allows requestors to access the complete task state without making an additional `tasks/get` request. +The notification includes the full task object, allowing clients to access the complete task state and final results without polling the `tasks/get` method. Clients **MAY** continue polling `tasks/get` in addition to subscribing to task status notifications, but need not do so. -Requestors **MUST NOT** rely on receiving this notifications, as it is optional. Receivers are not required to send status notifications and may choose to only send them for certain status transitions. Requestors **SHOULD** continue to poll via `tasks/get` to ensure they receive status updates. +`notifications/progress` and `notifications/message` notifications **MUST NOT** be sent on the `subscriptions/listen` stream for a task, and are not supported on tasks in general in this specification. -### Listing Tasks +## Streamable HTTP: Routing Headers -To retrieve a list of tasks, requestors can send a [`tasks/list`](https://modelcontextprotocol.io/specification/2025-11-25/schema#tasks%2Flist) request. This operation supports pagination. +When `tasks/get`, `tasks/update`, or `tasks/cancel` is sent over the Streamable HTTP transport, the client **MUST** set the `Mcp-Name` header to the value of `params.taskId`. This allows transport intermediaries and load balancers to route subsequent requests for the same task to the server instance holding its state, which is typically required for correctness. The `Mcp-Method` header is set to the JSON-RPC method name per standard header conventions. -**Request:** +## Example Message Flow -```json +Consider a simple tool call, `hello_world`, requiring an elicitation for the user to provide their name. The tool itself takes no arguments. + +To invoke this tool, the client makes a `CallToolRequest` as follows: + +```jsonc { "jsonrpc": "2.0", - "id": 5, - "method": "tasks/list", + "id": 2, + "method": "tools/call", "params": { - "cursor": "optional-cursor-value" - } + "name": "hello_world", + "arguments": {}, + "_meta": { + // Other metadata... + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, + }, } ``` -**Response:** +The server determines (via bespoke logic) that it wants to create a task to represent this work, and it immediately returns a `CreateTaskResult`: ```json { "jsonrpc": "2.0", - "id": 5, + "id": 2, "result": { - "tasks": [ - { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "working", - "createdAt": "2025-11-25T10:30:00Z", - "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 30000, - "pollInterval": 5000 - }, - { - "taskId": "abc123-def456-ghi789", - "status": "completed", - "createdAt": "2025-11-25T09:15:00Z", - "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 60000 - } - ], - "nextCursor": "next-page-cursor" + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 } } ``` -### Cancelling Tasks - -To explicitly cancel a task, requestors can send a [`tasks/cancel`](https://modelcontextprotocol.io/specification/2025-11-25/schema#tasks%2Fcancel) request. - -**Request:** +Once the client receives the `CreateTaskResult`, it begins polling `tasks/get`: ```json { "jsonrpc": "2.0", - "id": 6, - "method": "tasks/cancel", + "id": 3, + "method": "tasks/get", "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } ``` -**Response:** +On each request while the task is in a `"working"` status, the server returns a regular task response: ```json { "jsonrpc": "2.0", - "id": 6, + "id": 3, "result": { + "resultType": "complete", "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "cancelled", - "statusMessage": "The task was cancelled by request.", + "status": "working", "createdAt": "2025-11-25T10:30:00Z", - "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 30000, - "pollInterval": 5000 + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 } } ``` -## Behavior Requirements - -These requirements apply to all parties that support receiving task-augmented requests. - -### Task Support and Handling - -1. Receivers that do not declare the task capability for a request type **MUST** process requests of that type normally, ignoring any task-augmentation metadata if present. -1. Receivers that declare the task capability for a request type **MAY** return an error for non-task-augmented requests, requiring requestors to use task augmentation. - -### Task ID Requirements - -1. Task IDs **MUST** be a string value. -1. Task IDs **MUST** be generated by the receiver when creating a task. -1. Task IDs **MUST** be unique among all tasks controlled by the receiver. - -### Task Status Lifecycle - -1. Tasks **MUST** begin in the `working` status when created. -1. Receivers **MUST** only transition tasks through the following valid paths: - 1. From `working`: may move to `input_required`, `completed`, `failed`, or `cancelled` - 1. From `input_required`: may move to `working`, `completed`, `failed`, or `cancelled` - 1. Tasks with a `completed`, `failed`, or `cancelled` status are in a terminal state and **MUST NOT** transition to any other status - -**Task Status State Diagram:** - -```mermaid -stateDiagram-v2 - [*] --> working - - working --> input_required - working --> terminal - - input_required --> working - input_required --> terminal - - terminal --> [*] - - note right of terminal - Terminal states: - • completed - • failed - • cancelled - end note -``` - -### Input Required Status +Eventually, the server reaches the point at which it needs to send an elicitation to the user. It sets the task status to `"input_required"` to signal this. On the next `tasks/get` request from the client, the server sends the elicitation payload via the `inputRequests` field. -With the Streamable HTTP (SSE) transport, servers often close SSE streams after delivering a response message, which can lead to ambiguity regarding the stream used for subsequent task messages. - -Servers can handle this by enqueueing messages to the client to side-channel task-related messages alongside other responses. - -Servers have flexibility in how they manage SSE streams during task polling and result retrieval, and clients **SHOULD** expect messages to be delivered on any SSE stream, including the HTTP GET stream. -One possible approach is maintaining an SSE stream on `tasks/result` (see notes on the `input_required` status). -Where possible, servers **SHOULD NOT** upgrade to an SSE stream in response to a `tasks/get` request, as the client has indicated it wishes to poll for a result. - -While this note is not prescriptive regarding the specific usage of SSE streams, all implementations **MUST** continue to comply with the existing [Streamable HTTP transport specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server). +While task `inputRequests` share structural similarities with multi round-trip requests, they are a distinct mechanism: task `inputRequests` are surfaced via `tasks/get` and fulfilled via `tasks/update`, not via retries of the original method. A server that needs client input _before_ returning a `CreateTaskResult` (e.g. to decide whether to proceed) uses the multi round-trip request flow on the original request; a server that needs client input _during_ task execution uses the `inputRequests`/`inputResponses` mechanism described here. -1. When the task receiver has messagesfor the requestor that are necessary to complete the task, the receiver **SHOULD** move the task to the `input_required` status. -1. The receiver **MUST** include the `io.modelcontextprotocol/related-task` metadata in the request to associate it with the task. -1. When the requestor encounters the `input_required` status, it **SHOULD** preemptively call `tasks/result`. -1. When the receiver receives all required input, the task **SHOULD** transition out of `input_required` status (typically back to `working`). - -### TTL and Resource Management - -1. Receivers **MUST** include a `createdAt` [ISO 8601](https://datatracker.ietf.org/doc/html/rfc3339#section-5)-formatted timestamp in all task responses to indicate when the task was created. -1. Receivers **MUST** include a `lastUpdatedAt` [ISO 8601](https://datatracker.ietf.org/doc/html/rfc3339#section-5)-formatted timestamp in all task responses to indicate when the task was last updated. -1. Receivers **MAY** override the requested `ttl` duration. -1. Receivers **MUST** include the actual `ttl` duration (or `null` for unlimited) in `tasks/get` responses. -1. After a task's `ttl` lifetime has elapsed, receivers **MAY** delete the task and its results, regardless of the task status. -1. Receivers **MAY** include a `pollInterval` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. - -### Result Retrieval - -1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. -1. When a receiver receives a `tasks/result` request for a task in a terminal status (`completed`, `failed`, or `cancelled`), it **MUST** return the final result of the underlying request, whether that is a successful result or a JSON-RPC error. -1. When a receiver receives a `tasks/result` request for a task in any other non-terminal status (`working` or `input_required`), it **MUST** block the response until the task reaches a terminal status. -1. For tasks in a terminal status, receivers **MUST** return from `tasks/result` exactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error. - -### Associating Task-Related Messages - -1. All requests, notifications, and responses related to a task **MUST** include the `io.modelcontextprotocol/related-task` key in their `_meta` field, with the value set to an object with a `taskId` matching the associated task ID. - 1. For example, an elicitation that a task-augmented tool call depends on **MUST** share the same related task ID with that tool call's task. -1. For the `tasks/get`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. - Similarly, for the `tasks/get`, `tasks/list`, and `tasks/cancel` operations, receivers **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in the result messages, as the `taskId` is already present in the response structure. - -### Task Notifications - -1. Receivers **MAY** send `notifications/tasks/status` notifications when a task's status changes. -1. Requestors **MUST NOT** rely on receiving the `notifications/tasks/status` notification, as it is optional. -1. When sent, the `notifications/tasks/status` notification **SHOULD NOT** include the `io.modelcontextprotocol/related-task` metadata, as the task ID is already present in the notification parameters. - -### Task Progress Notifications - -Task-augmented requests support progress notifications as defined in the [progress](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress) specification. The `progressToken` provided in the initial request remains valid throughout the task lifetime. - -### Task Listing - -1. Receivers **SHOULD** use cursor-based pagination to limit the number of tasks returned in a single response. -1. Receivers **MUST** include a `nextCursor` in the response if more tasks are available. -1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them. -1. If a task is retrievable via `tasks/get` for a requestor, it **MUST** be retrievable via `tasks/list` for that requestor. - -### Task Cancellation - -1. Receivers **MUST** reject cancellation requests for tasks already in a terminal status (`completed`, `failed`, or `cancelled`) with error code `-32602` (Invalid params). -1. Upon receiving a valid cancellation request, receivers **SHOULD** attempt to stop the task execution and **MUST** transition the task to `cancelled` status before sending the response. -1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails. -1. The `tasks/cancel` operation does not define deletion behavior. However, receivers **MAY** delete cancelled tasks at their discretion at any time, including immediately after cancellation or after the task `ttl` expires. -1. Requestors **SHOULD NOT** rely on cancelled tasks being retained for any specific duration and should retrieve any needed information before cancelling. - -## Message Flow - -### Basic Task Lifecycle - -```mermaid -sequenceDiagram - participant C as Client (Requestor) - participant S as Server (Receiver) - Note over C,S: 1. Task Creation - C->>S: Request with task field (ttl) - activate S - S->>C: CreateTaskResult (taskId, status: working, ttl, pollInterval) - deactivate S - Note over C,S: 2. Task Polling - C->>S: tasks/get (taskId) - activate S - S->>C: working - deactivate S - Note over S: Task processing continues... - C->>S: tasks/get (taskId) - activate S - S->>C: working - deactivate S - Note over S: Task completes - C->>S: tasks/get (taskId) - activate S - S->>C: completed - deactivate S - Note over C,S: 3. Result Retrieval - C->>S: tasks/result (taskId) - activate S - S->>C: Result content - deactivate S - Note over C,S: 4. Cleanup - Note over S: After ttl period from creation, task is cleaned up -``` - -### Task-Augmented Tool Call With Elicitation - -```mermaid -sequenceDiagram - participant U as User - participant LLM - participant C as Client (Requestor) - participant S as Server (Receiver) - - Note over LLM,C: LLM initiates request - LLM->>C: Request operation - - Note over C,S: Client augments with task - C->>S: tools/call (ttl: 3600000) - activate S - S->>C: CreateTaskResult (task-123, status: working) - deactivate S - - Note over LLM,C: Client continues processing other requests
while task executes in background - LLM->>C: Request other operation - C->>LLM: Other operation result - - Note over C,S: Client polls for status - C->>S: tasks/get (task-123) - activate S - S->>C: working - deactivate S - - Note over S: Server needs information from client
Task moves to input_required - - Note over C,S: Client polls and discovers input_required - C->>S: tasks/get (task-123) - activate S - S->>C: input_required - deactivate S - - Note over C,S: Client opens result stream - C->>S: tasks/result (task-123) - activate S - S->>C: elicitation/create (related-task: task-123) - activate C - C->>U: Prompt user for input - U->>C: Provide information - C->>S: elicitation response (related-task: task-123) - deactivate C - deactivate S - - Note over C,S: Client closes result stream and resumes polling - - Note over S: Task continues processing...
Task moves back to working - - C->>S: tasks/get (task-123) - activate S - S->>C: working - deactivate S - - Note over S: Task completes - - Note over C,S: Client polls and discovers completion - C->>S: tasks/get (task-123) - activate S - S->>C: completed - deactivate S - - Note over C,S: Client retrieves final results - C->>S: tasks/result (task-123) - activate S - S->>C: Result content - deactivate S - C->>LLM: Process result - - Note over S: Results retained for ttl period from creation -``` - -### Task-Augmented Sampling Request - -```mermaid -sequenceDiagram - participant U as User - participant LLM - participant C as Client (Receiver) - participant S as Server (Requestor) - - Note over S: Server decides to initiate request - - Note over S,C: Server requests client operation (task-augmented) - S->>C: sampling/createMessage (ttl: 3600000) - activate C - C->>S: CreateTaskResult (request-789, status: working) - deactivate C - - Note over S: Server continues processing
while waiting for result - - Note over S,C: Server polls for result - S->>C: tasks/get (request-789) - activate C - C->>S: working - deactivate C - - Note over C,U: Client may present request to user - C->>U: Review request - U->>C: Approve request - - Note over C,LLM: Client may involve LLM - C->>LLM: Request completion - LLM->>C: Return completion - - Note over C,U: Client may present result to user - C->>U: Review result - U->>C: Approve result - - Note over S,C: Server polls and discovers completion - S->>C: tasks/get (request-789) - activate C - C->>S: completed - deactivate C - - Note over S,C: Server retrieves result - S->>C: tasks/result (request-789) - activate C - C->>S: Result content - deactivate C - - Note over S: Server continues processing - - Note over C: Results retained for ttl period from creation +```json +{ + "jsonrpc": "2.0", + "id": 4, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} ``` -### Task Cancellation Flow - -```mermaid -sequenceDiagram - participant C as Client (Requestor) - participant S as Server (Receiver) - - Note over C,S: 1. Task Creation - C->>S: tools/call (request ID: 42, ttl: 60000) - activate S - S->>C: CreateTaskResult (task-123, status: working) - deactivate S - - Note over C,S: 2. Task Processing - C->>S: tasks/get (task-123) - activate S - S->>C: working - deactivate S - - Note over C,S: 3. Client Cancellation - Note over C: User requests cancellation - C->>S: tasks/cancel (taskId: task-123) - activate S - - Note over S: Server stops execution (best effort) - Note over S: Task moves to cancelled status - - S->>C: Task (status: cancelled) - deactivate S - - Note over C: Client receives confirmation - - Note over S: Server may delete task at its discretion +```json +{ + "id": 4, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "input_required", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "inputRequests": { + "name": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Please enter your name.", + "requestedSchema": { + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + } + } + } + } + } +} ``` -## Data Types +For thoroughness, consider a case where the client happens to poll `tasks/get` again _before_ the user has fulfilled the elicitation request. As `inputRequests` is effectively a point-in-time snapshot of all outstanding server-to-client requests associated with the task, the server includes the same request again, despite the client having already seen this information (the client is advised to deduplicate `inputRequests` with the same key for UX purposes): -### Task - -A task represents the execution state of a request. The task state includes: - -- `taskId`: Unique identifier for the task -- `status`: Current state of the task execution -- `statusMessage`: Optional human-readable message describing the current state (can be present for any status, including error details for failed tasks) -- `createdAt`: ISO 8601 timestamp when the task was created -- `ttl`: Time in milliseconds from creation before task may be deleted -- `pollInterval`: Suggested time in milliseconds between status checks -- `lastUpdatedAt`: ISO 8601 timestamp when the task status was last updated - -### Task Status +```json +{ + "jsonrpc": "2.0", + "id": 5, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` -Tasks can be in one of the following states: +```json +{ + "id": 5, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "input_required", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "inputRequests": { + "name": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Please enter your name.", + "requestedSchema": { + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + } + } + } + } + } +} +``` -- `working`: The request is currently being processed. -- `input_required`: The receiver needs input from the requestor. The requestor should call `tasks/result` to receive input requests, even though the task has not reached a terminal state. -- `completed`: The request completed successfully and results are available. -- `failed`: The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result has `isError` set to true. -- `cancelled`: The request was cancelled before completion. +The user enters their name, and the client makes a `tasks/update` request with the satisfied information: -### Task Parameters +```json +{ + "jsonrpc": "2.0", + "id": 6, + "method": "tasks/update", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "inputResponses": { + "name": { + "action": "accept", + "content": { + "input": "Luca" + } + } + } + } +} +``` -When augmenting a request with task execution, the `task` field is included in the request parameters: +The server acknowledges the request: ```json { - "task": { - "ttl": 60000 + "jsonrpc": "2.0", + "id": 6, + "result": { + "resultType": "complete" } } ``` -Fields: +Asynchronously, the server processes the input and moves the task back into the `working` status: -- `ttl` (number, optional): Requested duration in milliseconds to retain task from creation +```json +{ + "jsonrpc": "2.0", + "id": 7, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` -### Related Task Metadata +```json +{ + "id": 7, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 + } +} +``` -All requests, responses, and notifications associated with a task **MUST** include the `io.modelcontextprotocol/related-task` key in `_meta`: +Eventually, the server completes the request, so it stores the final `CallToolResult` and moves the task into the `"completed"` status. On the next `tasks/get` request, the server sends the final tool result inlined into the task object: ```json { - "io.modelcontextprotocol/related-task": { + "jsonrpc": "2.0", + "id": 8, + "method": "tasks/get", + "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } ``` -This associates messages with their originating task across the entire request lifecycle. - -For the `tasks/get`, `tasks/list`, and `tasks/cancel` operations, requestors and receivers **SHOULD NOT** include this metadata in their messages, as the `taskId` is already present in the message structure. -The `tasks/result` operation **MUST** include this metadata in its response, as the result structure itself does not contain the task ID. +```json +{ + "jsonrpc": "2.0", + "id": 8, + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "completed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "result": { + "content": [ + { + "type": "text", + "text": "Hello, Luca!" + } + ], + "isError": false + } + } +} +``` ## Error Handling Tasks use two error reporting mechanisms: 1. **Protocol Errors**: Standard JSON-RPC errors for protocol-level issues -1. **Task Execution Errors**: Errors in the underlying request execution, reported through task status +2. **Task Execution Errors**: Errors in the underlying request execution, reported through task status ### Protocol Errors -Receivers **MUST** return standard JSON-RPC errors for the following protocol error cases: +Servers **MUST** return standard JSON-RPC errors for the following protocol error cases: -- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/result`, or `tasks/cancel`: `-32602` (Invalid params) -- Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) -- Attempt to cancel a task already in a terminal status: `-32602` (Invalid params) +- Invalid or nonexistent `taskId`: `-32602` (Invalid params) + - Servers **MUST** return this error for `tasks/get`. + - Servers **SHOULD** return this error for `tasks/update` and `tasks/cancel`. - Internal errors: `-32603` (Internal error) -Additionally, receivers **MAY** return the following errors: - -- Non-task-augmented request when receiver requires task augmentation for that request type: `-32600` (Invalid request) - -Receivers **SHOULD** provide informative error messages to describe the cause of errors. - -**Example: Task augmentation required** - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32600, - "message": "Task augmentation required for tools/call requests" - } -} -``` +Servers **SHOULD** provide informative error messages to describe the cause of errors. **Example: Task not found** @@ -822,84 +829,85 @@ Receivers **SHOULD** provide informative error messages to describe the cause of -Receivers are not required to retain tasks indefinitely. It is compliant behavior for a receiver to return an error stating the task cannot be found if it has purged an expired task. +Servers are not required to retain tasks indefinitely. It is compliant behavior for a server to return an error stating the task cannot be found if it has purged an expired task. -**Example: Task cancellation rejected (already terminal)** +### Task Execution Errors + +When the underlying request encounters a JSON-RPC protocol error during execution, the task moves to the `failed` status. The `tasks/get` response **SHOULD** include a `statusMessage` field with diagnostic information about the failure, and **MUST** include the `error` field with the JSON-RPC error. + +The `failed` status **MUST NOT** be used to represent non-JSON-RPC errors, such as a tool result that completed with `isError: true`. Errors within the context of a protocol method result **MUST** use the `completed` status with the error details in the `result` field. This maintains a strong separation between protocol-level faults (which use the `failed` status) and other faults. + +**Example: Task with JSON-RPC execution error** ```json { "jsonrpc": "2.0", - "id": 74, - "error": { - "code": -32602, - "message": "Cannot cancel task: already in terminal status 'completed'" + "id": 4, + "result": { + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f820fe840", + "status": "failed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:40:00Z", + "ttlMs": 3600000, + "statusMessage": "Tool execution failed: API rate limit exceeded", + "error": { + "code": -32603, + "message": "API rate limit exceeded" + } } } ``` -### Task Execution Errors - -When the underlying request does not complete successfully, the task moves to the `failed` status. This includes JSON-RPC protocol errors during request execution, or for tool calls specifically, when the tool result has `isError` set to true. The `tasks/get` response **SHOULD** include a `statusMessage` field with diagnostic information about the failure. +**Example: Tool call completed with tool error (isError: true)** -**Example: Task with execution error** +For tool calls that complete successfully at the protocol level but return a tool-level error (indicated by `isError: true` in the tool result), the task reaches `completed` status with the tool result in the `result` field: ```json { "jsonrpc": "2.0", - "id": 4, + "id": 5, "result": { + "resultType": "task", "taskId": "786512e2-9e0d-44bd-8f29-789f820fe840", - "status": "failed", + "status": "completed", "createdAt": "2025-11-25T10:30:00Z", "lastUpdatedAt": "2025-11-25T10:40:00Z", - "ttl": 30000, - "statusMessage": "Tool execution failed: API rate limit exceeded" + "ttlMs": 3600000, + "result": { + "content": [ + { + "type": "text", + "text": "Failed to process request: invalid input" + } + ], + "isError": true + } } } ``` -For tasks that wrap tool call requests, when the tool result has `isError` set to `true`, the task should reach `failed` status. - -The `tasks/result` endpoint returns exactly what the underlying request would have returned: +The `tasks/get` endpoint returns exactly what the underlying request would have returned: -- If the underlying request resulted in a JSON-RPC error, `tasks/result` **MUST** return that same JSON-RPC error. -- If the request completed with a JSON-RPC response, `tasks/result` **MUST** return a successful JSON-RPC response containing that result. +- If the underlying request resulted in a JSON-RPC error, the task uses `failed` status and the `error` field **MUST** contain that JSON-RPC error. +- If the request completed with a result (even if `isError: true` for tool results), the task uses `completed` status and the `result` field **MUST** contain that result. -## Security Considerations +## Reservations -### Task Isolation and Access Control +- The `tasks/` method prefix and `notifications/tasks/` notification prefix are reserved for this extension. +- The result-discriminator value `"task"` for `resultType` is reserved for this extension. +- The label `io.modelcontextprotocol/tasks` is reserved for this extension. -Task IDs are the primary mechanism for accessing task state and results. Without proper access controls, any party that can guess or obtain a task ID could potentially access sensitive information or manipulate tasks they did not create. - -When an authorization context is provided, receivers **MUST** bind tasks to said context. - -Context-binding is not practical for all applications. Some MCP servers operate in environments without authorization, such as single-user tools, or use transports that don't support authorization. -In these scenarios, receivers **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. -If context-binding is unavailable, receivers **MUST** generate cryptographically secure task IDs with enough entropy to prevent guessing and should consider using shorter TTL durations to reduce the exposure window. -Furthermore, receivers that cannot identify requestors **SHOULD NOT** declare the `tasks.list` capability, as listing tasks would expose task metadata to any requestor regardless of task ID entropy. - -If context-binding is available, receivers **MUST** reject `tasks/get`, `tasks/result`, and `tasks/cancel` requests for tasks that do not belong to the same authorization context as the requestor. For `tasks/list` requests, receivers **MUST** ensure the returned task list includes only tasks associated with the requestor's authorization context. - -Additionally, receivers **SHOULD** implement rate limiting on task operations to prevent denial-of-service and enumeration attacks. +## Security Considerations -### Resource Management +- **Task ID unguessability.** A server **MAY** use task IDs as bearer tokens for a server's stored state. Servers **MUST** generate them with sufficient entropy that a third party cannot enumerate or guess them. +- **Cross-caller correlation.** Because there is no `tasks/list`, a server cannot inadvertently leak the existence of one caller's tasks to another. This is an improvement over the `2025-11-25` tasks specification, in which a poorly-scoped list could expose unrelated task IDs. +- **Input-request trust model.** `inputRequests` carry elicitation and sampling payloads from the server through the client to the user or model. Hosts **MUST** apply the same trust model to these payloads as they would to standard elicitation/sampling requests. A task is not a higher-trust channel. -1. Receivers **SHOULD**: - 1. Enforce limits on concurrent tasks per requestor - 1. Enforce maximum `ttl` durations to prevent indefinite resource retention - 1. Clean up expired tasks promptly to free resources - 1. Document maximum supported `ttl` duration - 1. Document maximum concurrent tasks per requestor - 1. Implement monitoring and alerting for resource usage +## Implementation Considerations -### Audit and Logging +### Backwards Compatibility -1. Receivers **SHOULD**: - 1. Log task creation, completion, and retrieval events for audit purposes - 1. Include auth context in logs when available - 1. Monitor for suspicious patterns (e.g., many failed task lookups, excessive polling) -1. Requestors **SHOULD**: - 1. Log task lifecycle events for debugging and audit purposes - 1. Track task IDs and their associated operations +- `2025-11-25` client implementations returning fixed shapes (e.g., a `tools/call` method returning `CallToolResult`) need not change their public method contracts — they can transparently drive the polling flow internally and surface only the final, completed result. New implementation surfaces can then expose the task lifecycle directly for applications able to leverage it. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ba6e32f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3068 @@ +{ + "name": "@modelcontextprotocol/experimental-ext-tasks", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@modelcontextprotocol/experimental-ext-tasks", + "version": "0.1.0", + "license": "Apache-2.0", + "devDependencies": { + "@modelcontextprotocol/sdk": "^1.29.0", + "ts-to-zod": "^5.1.0", + "tsx": "^4.21.0", + "typescript": "^5.0.0", + "zod": "^4.4.3" + } + }, + "node_modules/@clack/core": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.0-alpha.4.tgz", + "integrity": "sha512-VCtU+vjyKPMSakVrB9q1bOnXN7QW/w4+YQDQCOF59GrzydW+169i0fVx/qzRRXJgt8KGj/pZZ/JxXroFZIDByg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.0-alpha.4.tgz", + "integrity": "sha512-KnmtDF2xQGoI5AlBme9akHtvCRV0RKAARUXHBQO2tMwnY8B08/4zPWigT7uLK25UPrMCEqnyQPkKRjNdhPbf8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/core": "1.0.0-alpha.4", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", + "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.19.9", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@oclif/core": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.11.2.tgz", + "integrity": "sha512-LWDalCgy+hYyAkLa9sMIXMXk6ws5RzQhVnkmfXtVIIyEEYigbXQ/9/x+s76p53MiXxNc6SJB7lfwkPF+SdzfMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "ansis": "^3.17.0", + "clean-stack": "^3.0.1", + "cli-spinners": "^2.9.2", + "debug": "^4.4.3", + "ejs": "^3.1.10", + "get-package-type": "^0.1.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "lilconfig": "^3.1.3", + "minimatch": "^10.2.5", + "semver": "^7.8.0", + "string-width": "^4.2.3", + "supports-color": "^8", + "tinyglobby": "^0.2.14", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@typescript/vfs": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.4.tgz", + "integrity": "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz", + "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.1.tgz", + "integrity": "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.12.18", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", + "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jose": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/text-camel-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.10.tgz", + "integrity": "sha512-KNrWeZzQT+gh73V1LnmgTkjK7V+tMRjLCc6VrGwkqbiRdnGVIWBUgIvVnvnaVCxIvZ/2Ke8DCmgPirlQcCqD3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-pascal-case": "1.2.10" + } + }, + "node_modules/text-capital-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.10.tgz", + "integrity": "sha512-yvViUJKSSQcRO58je224bhPHg/Hij9MEY43zuKShtFzrPwW/fOAarUJ5UkTMSB81AOO1m8q+JiFdxMF4etKZbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" + } + }, + "node_modules/text-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.10.tgz", + "integrity": "sha512-5bY3Ks/u7OJ5YO69iyXrG5Xf2wUZeyko7U78nPUnYoSeuNeAfA5uAix5hTspfkl6smm3yCBObrex+kFvzeIcJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-camel-case": "1.2.10", + "text-capital-case": "1.2.10", + "text-constant-case": "1.2.10", + "text-dot-case": "1.2.10", + "text-header-case": "1.2.10", + "text-is-lower-case": "1.2.10", + "text-is-upper-case": "1.2.10", + "text-kebab-case": "1.2.10", + "text-lower-case": "1.2.10", + "text-lower-case-first": "1.2.10", + "text-no-case": "1.2.10", + "text-param-case": "1.2.10", + "text-pascal-case": "1.2.10", + "text-path-case": "1.2.10", + "text-sentence-case": "1.2.10", + "text-snake-case": "1.2.10", + "text-swap-case": "1.2.10", + "text-title-case": "1.2.10", + "text-upper-case": "1.2.10", + "text-upper-case-first": "1.2.10" + } + }, + "node_modules/text-constant-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.10.tgz", + "integrity": "sha512-/OfU798O2wrwKN9kQf71WhJeAlklGnbby0Tupp+Ez9NXymW+6oF9LWDRTkN+OreTmHucdvp4WQd6O5Rah5zj8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10", + "text-upper-case": "1.2.10" + } + }, + "node_modules/text-dot-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.10.tgz", + "integrity": "sha512-vf4xguy5y6e39RlDZeWZFMDf2mNkR23VTSVb9e68dUSpfJscG9/1YWWpW3n8TinzQxBZlsn5sT5olL33MvvQXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10" + } + }, + "node_modules/text-header-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.10.tgz", + "integrity": "sha512-sVb1NY9bwxtu+Z7CVyWbr+I0AkWtF0kEHL/Zz5V2u/WdkjK5tKBwl5nXf0NGy9da4ZUYTBb+TmQpOIqihzvFMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-capital-case": "1.2.10" + } + }, + "node_modules/text-is-lower-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.10.tgz", + "integrity": "sha512-dMTeTgrdWWfYf3fKxvjMkDPuXWv96cWbd1Uym6Zjv9H855S1uHxjkFsGbTYJ2tEK0NvAylRySTQlI6axlcMc4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-is-upper-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.10.tgz", + "integrity": "sha512-PGD/cXoXECGAY1HVZxDdmpJUW2ZUAKQ6DTamDfCHC9fc/z4epOz0pB/ThBnjJA3fz+d2ApkMjAfZDjuZFcodzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-kebab-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.10.tgz", + "integrity": "sha512-3XZJAApx5JQpUO7eXo7GQ2TyRcGw3OVbqxz6QJb2h+N8PbLLbz3zJVeXdGrhTkoUIbkSZ6PmHx6LRDaHXTdMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10" + } + }, + "node_modules/text-lower-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.10.tgz", + "integrity": "sha512-c9j5pIAN3ObAp1+4R7970e1bgtahTRF/5ZQdX2aJBuBngYTYZZIck0NwFXUKk5BnYpLGsre5KFHvpqvf4IYKgg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-lower-case-first": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.10.tgz", + "integrity": "sha512-Oro84jZPDLD9alfdZWmtFHYTvCaaSz2o4thPtjMsK4GAkTyVg9juYXWj0y0YFyjLYGH69muWsBe4/MR5S7iolw==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-no-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.10.tgz", + "integrity": "sha512-4/m79pzQrywrwEG5lCULY1lQvFY+EKjhH9xSMT6caPK5plqzm9Y7rXyv+UXPd3s9qH6QODZnvsAYWW3M0JgxRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-lower-case": "1.2.10" + } + }, + "node_modules/text-param-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.10.tgz", + "integrity": "sha512-hkavcLsRRzZcGryPAshct1AwIOMj/FexYjMaLpGZCYYBn1lcZEeyMzJZPSckzkOYpq35LYSQr3xZto9XU5OAsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.10" + } + }, + "node_modules/text-pascal-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.10.tgz", + "integrity": "sha512-/kynZD8vTYOmm/RECjIDaz3qYEUZc/N/bnC79XuAFxwXjdNVjj/jGovKJLRzqsYK/39N22XpGcVmGg7yIrbk6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10" + } + }, + "node_modules/text-path-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.10.tgz", + "integrity": "sha512-vbKdRCaVEeOaW6sm24QP9NbH7TS9S4ZQ3u19H8eylDox7m2HtFwYIBjAPv+v3z4I/+VjrMy9LB54lNP1uEqRHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.10" + } + }, + "node_modules/text-sentence-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.10.tgz", + "integrity": "sha512-NO4MRlbfxFhl9QgQLuCL4xHmvE7PUWHVPWsZxQ5nzRtDjXOUllWvtsvl8CP5tBEvBmzg0kwfflxfhRtr5vBQGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" + } + }, + "node_modules/text-snake-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.10.tgz", + "integrity": "sha512-6ttMZ+B9jkHKun908HYr4xSvEtlbfJJ4MvpQ06JEKRGhwjMI0x8t2Wywp+MEzN6142O6E/zKhra18KyBL6cvXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.10" + } + }, + "node_modules/text-swap-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.10.tgz", + "integrity": "sha512-vO3jwInIk0N77oEFakYZ2Hn/llTmRwf2c3RvkX/LfvmLWVp+3QcIc6bwUEtbqGQ5Xh2okjFhYrfkHZstVc3N4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-title-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.10.tgz", + "integrity": "sha512-bqA+WWexUMWu9A3fdNar+3GXXW+c5xOvMyuK5hOx/w0AlqhyQptyCrMFjGB8Fd9dxbryBNmJ+5rWtC1OBDxlaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" + } + }, + "node_modules/text-upper-case": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.10.tgz", + "integrity": "sha512-L1AtZ8R+jtSMTq0Ffma9R4Rzbrc3iuYW89BmWFH41AwnDfRmEBlBOllm1ZivRLQ/6pEu2p+3XKBHx9fsMl2CWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-upper-case-first": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.10.tgz", + "integrity": "sha512-VXs7j7BbpKwvolDh5fwpYRmMrUHGkxbY8E90fhBzKUoKfadvWmPT/jFieoZ4UPLzr208pXvQEFbb2zO9Qzs9Fg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-to-zod": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ts-to-zod/-/ts-to-zod-5.1.0.tgz", + "integrity": "sha512-giqqlvRHunlJqG9tBL/KAO3wWIVZGF//mZiWLKm/fdQnKnz4EN2mtiK5cugN9slytBkdMEXQIaLvMzIScbhhFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/prompts": "1.0.0-alpha.4", + "@oclif/core": "^4.5.4", + "@typescript/vfs": "^1.5.0", + "chokidar": "^4.0.3", + "listr2": "^9.0.4", + "slash": "^5.1.0", + "text-case": "^1.2.4", + "tslib": "^2.3.1", + "tsutils": "^3.21.0", + "typescript": "^5.2.2", + "zod": "^4.1.5" + }, + "bin": { + "ts-to-zod": "bin/run" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + } + } +} diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 5f657c2..dafda16 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -50,6 +50,137 @@ "additionalProperties": false }, "CancelTaskResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "progressToken": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "io.modelcontextprotocol/related-task": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + } + }, + "required": [ + "taskId" + ], + "additionalProperties": false + } + }, + "additionalProperties": {} + } + }, + "additionalProperties": {} + }, + "CancelledTask": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "cancelled" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false + }, + "CompletedTask": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "completed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "result": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "result" + ], + "additionalProperties": false + }, + "CreateTaskResult": { "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { @@ -127,7 +258,7 @@ "lastUpdatedAt": { "type": "string" }, - "ttl": { + "ttlMs": { "anyOf": [ { "type": "number" @@ -137,7 +268,7 @@ } ] }, - "pollInterval": { + "pollIntervalMs": { "type": "number" } }, @@ -146,76 +277,123 @@ "status", "createdAt", "lastUpdatedAt", - "ttl" + "ttlMs" ], "additionalProperties": false } ] }, - "CreateTaskResult": { + "DetailedTask": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "_meta": { + "anyOf": [ + { "type": "object", "properties": { - "progressToken": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "working" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 + "type": "null" } ] }, - "io.modelcontextprotocol/related-task": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - }, - "required": [ - "taskId" - ], - "additionalProperties": false + "pollIntervalMs": { + "type": "number" } }, - "additionalProperties": {} + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false }, - "task": { + { "type": "object", "properties": { "taskId": { "type": "string" }, "status": { + "type": "string", + "const": "input_required" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { "anyOf": [ { - "type": "string", - "const": "working" - }, - { - "type": "string", - "const": "input_required" - }, - { - "type": "string", - "const": "completed" - }, - { - "type": "string", - "const": "failed" + "type": "number" }, { - "type": "string", - "const": "cancelled" + "type": "null" } ] }, + "pollIntervalMs": { + "type": "number" + }, + "inputRequests": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "inputRequests" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "completed" + }, "statusMessage": { "type": "string" }, @@ -225,7 +403,7 @@ "lastUpdatedAt": { "type": "string" }, - "ttl": { + "ttlMs": { "anyOf": [ { "type": "number" @@ -235,8 +413,15 @@ } ] }, - "pollInterval": { + "pollIntervalMs": { "type": "number" + }, + "result": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } }, "required": [ @@ -244,108 +429,155 @@ "status", "createdAt", "lastUpdatedAt", - "ttl" + "ttlMs", + "result" ], "additionalProperties": false - } - }, - "required": [ - "task" - ], - "additionalProperties": {} - }, - "GetTaskPayloadRequest": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "jsonrpc": { - "type": "string", - "const": "2.0" }, - "id": { - "anyOf": [ - { + { + "type": "object", + "properties": { + "taskId": { "type": "string" }, - { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 + "status": { + "type": "string", + "const": "failed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "error": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } - ] - }, - "method": { - "type": "string", - "const": "tasks/result" + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "error" + ], + "additionalProperties": false }, - "params": { + { "type": "object", "properties": { "taskId": { "type": "string" + }, + "status": { + "type": "string", + "const": "cancelled" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" } }, "required": [ - "taskId" + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" ], "additionalProperties": false } - }, - "required": [ - "jsonrpc", - "id", - "method", - "params" - ], - "additionalProperties": false + ] }, - "GetTaskPayloadResult": { + "FailedTask": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "allOf": [ - { - "type": "object", - "properties": { - "_meta": { - "type": "object", - "properties": { - "progressToken": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 - } - ] - }, - "io.modelcontextprotocol/related-task": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - }, - "required": [ - "taskId" - ], - "additionalProperties": false - } - }, - "additionalProperties": {} + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "failed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" } - }, - "additionalProperties": {} + ] }, - { + "pollIntervalMs": { + "type": "number" + }, + "error": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } - ] + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "error" + ], + "additionalProperties": false }, "GetTaskRequest": { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -432,354 +664,352 @@ "additionalProperties": {} }, { - "type": "object", - "properties": { - "taskId": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "type": "string", - "const": "working" + "anyOf": [ + { + "type": "object", + "properties": { + "taskId": { + "type": "string" }, - { + "status": { "type": "string", - "const": "input_required" + "const": "working" }, - { - "type": "string", - "const": "completed" + "statusMessage": { + "type": "string" }, - { - "type": "string", - "const": "failed" + "createdAt": { + "type": "string" }, - { - "type": "string", - "const": "cancelled" - } - ] - }, - "statusMessage": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastUpdatedAt": { - "type": "string" - }, - "ttl": { - "anyOf": [ - { - "type": "number" + "lastUpdatedAt": { + "type": "string" }, - { - "type": "null" - } - ] - }, - "pollInterval": { - "type": "number" - } - }, - "required": [ - "taskId", - "status", - "createdAt", - "lastUpdatedAt", - "ttl" - ], - "additionalProperties": false - } - ] - }, - "ListTasksRequest": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "method": { - "type": "string", - "const": "tasks/list" - }, - "params": { - "type": "object", - "properties": { - "_meta": { - "type": "object", - "properties": { - "progressToken": { + "ttlMs": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 + "type": "null" } ] }, - "io.modelcontextprotocol/related-task": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - }, - "required": [ - "taskId" - ], - "additionalProperties": false + "pollIntervalMs": { + "type": "number" } }, - "additionalProperties": {} + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false }, - "cursor": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "method" - ], - "additionalProperties": false - }, - "ListTasksResult": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "_meta": { - "type": "object", - "properties": { - "progressToken": { - "anyOf": [ - { + { + "type": "object", + "properties": { + "taskId": { "type": "string" }, - { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 + "status": { + "type": "string", + "const": "input_required" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "inputRequests": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } } - ] + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "inputRequests" + ], + "additionalProperties": false }, - "io.modelcontextprotocol/related-task": { + { "type": "object", "properties": { "taskId": { "type": "string" + }, + "status": { + "type": "string", + "const": "completed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "result": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } }, "required": [ - "taskId" + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "result" ], "additionalProperties": false - } - }, - "additionalProperties": {} - }, - "nextCursor": { - "type": "string" - }, - "tasks": { - "type": "array", - "items": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "type": "string", - "const": "working" - }, - { - "type": "string", - "const": "input_required" - }, - { - "type": "string", - "const": "completed" - }, - { - "type": "string", - "const": "failed" - }, - { - "type": "string", - "const": "cancelled" - } - ] - }, - "statusMessage": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastUpdatedAt": { - "type": "string" - }, - "ttl": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "pollInterval": { - "type": "number" - } }, - "required": [ - "taskId", - "status", - "createdAt", - "lastUpdatedAt", - "ttl" - ], - "additionalProperties": false - } - } - }, - "required": [ - "tasks" - ], - "additionalProperties": {} - }, - "RelatedTaskMetadata": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - }, - "required": [ - "taskId" - ], - "additionalProperties": false - }, - "TaskAugmentedRequestParams": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "_meta": { - "type": "object", - "properties": { - "progressToken": { - "anyOf": [ - { + { + "type": "object", + "properties": { + "taskId": { "type": "string" }, - { - "type": "integer", - "minimum": -9007199254740991, - "maximum": 9007199254740991 + "status": { + "type": "string", + "const": "failed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "error": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } - ] - } - }, - "additionalProperties": {} - }, - "task": { - "type": "object", - "properties": { - "ttl": { - "type": "number" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": {} - }, - "TaskClientCapabilities": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "tasks": { - "type": "object", - "properties": { - "list": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "not": {} - } - }, - "cancel": { - "type": "object", - "propertyNames": { - "type": "string" }, - "additionalProperties": { - "not": {} - } + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "error" + ], + "additionalProperties": false }, - "requests": { + { "type": "object", "properties": { - "sampling": { - "type": "object", - "properties": { - "createMessage": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "not": {} - } - } - }, - "additionalProperties": false + "taskId": { + "type": "string" }, - "elicitation": { - "type": "object", - "properties": { - "create": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "not": {} - } + "status": { + "type": "string", + "const": "cancelled" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" } - }, - "additionalProperties": false + ] + }, + "pollIntervalMs": { + "type": "number" } }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], "additionalProperties": false } - }, - "additionalProperties": false + ] } + ] + }, + "InputRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + {}, + {}, + {} + ] + }, + "InputRequests": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "propertyNames": { + "type": "string" }, - "additionalProperties": false + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } }, - "TaskMetadata": { + "InputRequiredTask": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { - "ttl": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "input_required" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { "type": "number" + }, + "inputRequests": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } } }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "inputRequests" + ], "additionalProperties": false }, + "InputResponse": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + {}, + {}, + {} + ] + }, + "InputResponses": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } + }, "Task": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", @@ -820,7 +1050,7 @@ "lastUpdatedAt": { "type": "string" }, - "ttl": { + "ttlMs": { "anyOf": [ { "type": "number" @@ -830,7 +1060,7 @@ } ] }, - "pollInterval": { + "pollIntervalMs": { "type": "number" } }, @@ -839,139 +1069,269 @@ "status", "createdAt", "lastUpdatedAt", - "ttl" + "ttlMs" ], "additionalProperties": false }, - "TaskServerCapabilities": { + "TaskStatusNotificationParams": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "tasks": { + "allOf": [ + { "type": "object", "properties": { - "list": { + "_meta": { "type": "object", "propertyNames": { "type": "string" }, - "additionalProperties": { - "not": {} - } + "additionalProperties": {} + } + }, + "additionalProperties": {} + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "working" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "input_required" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "inputRequests": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "inputRequests" + ], + "additionalProperties": false }, - "cancel": { + { "type": "object", - "propertyNames": { - "type": "string" + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "completed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "result": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } }, - "additionalProperties": { - "not": {} - } + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "result" + ], + "additionalProperties": false }, - "requests": { + { "type": "object", "properties": { - "tools": { - "type": "object", - "properties": { - "call": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "not": {} - } + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "failed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "error": { + "type": "object", + "propertyNames": { + "type": "string" }, - "additionalProperties": false + "additionalProperties": {} } }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "error" + ], "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "TaskStatusNotificationParams": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "allOf": [ - { - "type": "object", - "properties": { - "_meta": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - }, - "additionalProperties": {} - }, - { - "type": "object", - "properties": { - "taskId": { - "type": "string" }, - "status": { - "anyOf": [ - { - "type": "string", - "const": "working" + { + "type": "object", + "properties": { + "taskId": { + "type": "string" }, - { + "status": { "type": "string", - "const": "input_required" + "const": "cancelled" }, - { - "type": "string", - "const": "completed" + "statusMessage": { + "type": "string" }, - { - "type": "string", - "const": "failed" + "createdAt": { + "type": "string" }, - { - "type": "string", - "const": "cancelled" - } - ] - }, - "statusMessage": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastUpdatedAt": { - "type": "string" - }, - "ttl": { - "anyOf": [ - { - "type": "number" + "lastUpdatedAt": { + "type": "string" }, - { - "type": "null" + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" } - ] - }, - "pollInterval": { - "type": "number" + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false } - }, - "required": [ - "taskId", - "status", - "createdAt", - "lastUpdatedAt", - "ttl" - ], - "additionalProperties": false + ] }, { "type": "object", @@ -1010,66 +1370,248 @@ "additionalProperties": {} }, { - "type": "object", - "properties": { - "taskId": { - "type": "string" - }, - "status": { - "anyOf": [ - { + "anyOf": [ + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { "type": "string", "const": "working" }, - { + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { "type": "string", "const": "input_required" }, - { + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "inputRequests": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "inputRequests" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { "type": "string", "const": "completed" }, - { - "type": "string", - "const": "failed" + "statusMessage": { + "type": "string" }, - { - "type": "string", - "const": "cancelled" + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + }, + "result": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } - ] - }, - "statusMessage": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastUpdatedAt": { - "type": "string" + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "result" + ], + "additionalProperties": false }, - "ttl": { - "anyOf": [ - { + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "failed" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { "type": "number" }, - { - "type": "null" + "error": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} } - ] + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs", + "error" + ], + "additionalProperties": false }, - "pollInterval": { - "type": "number" + { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string", + "const": "cancelled" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" + } + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false } - }, - "required": [ - "taskId", - "status", - "createdAt", - "lastUpdatedAt", - "ttl" - ], - "additionalProperties": false + ] }, { "type": "object", @@ -1113,22 +1655,180 @@ } ] }, - "ToolTaskSupport": { + "TaskSubscriptionAcknowledgedNotifications": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ - { + "type": "object", + "properties": { + "tasksStatus": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "TaskSubscriptionNotifications": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "tasksStatus": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "TasksExtensionCapability": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "not": {} + } + }, + "UpdateTaskRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "jsonrpc": { "type": "string", - "const": "forbidden" + "const": "2.0" }, - { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "method": { "type": "string", - "const": "optional" + "const": "tasks/update" }, - { + "params": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "inputResponses": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "anyOf": [ + {}, + {}, + {} + ] + } + } + }, + "required": [ + "taskId", + "inputResponses" + ], + "additionalProperties": false + } + }, + "required": [ + "jsonrpc", + "id", + "method", + "params" + ], + "additionalProperties": false + }, + "UpdateTaskResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "progressToken": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "io.modelcontextprotocol/related-task": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + } + }, + "required": [ + "taskId" + ], + "additionalProperties": false + } + }, + "additionalProperties": {} + } + }, + "additionalProperties": {} + }, + "WorkingTask": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { "type": "string", - "const": "required" + "const": "working" + }, + "statusMessage": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastUpdatedAt": { + "type": "string" + }, + "ttlMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pollIntervalMs": { + "type": "number" } - ] + }, + "required": [ + "taskId", + "status", + "createdAt", + "lastUpdatedAt", + "ttlMs" + ], + "additionalProperties": false } } } diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 05771c8..2634c47 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -8,19 +8,19 @@ * - Use `@description` JSDoc tags to generate `.describe()` calls on schemas * - Run `npm run generate:schemas` to regenerate schemas from these types * - * @see https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks + * @see https://modelcontextprotocol.io/seps/2663-tasks-extension */ import type { - Cursor, + CreateMessageRequest, + CreateMessageResult, + ElicitRequest, + ElicitResult, JSONRPCNotification, JSONRPCRequest, + ListRootsRequest, + ListRootsResult, NotificationParams, - PaginatedRequest, - PaginatedResult, - ProgressToken, - RequestId, - RequestParams, Result, } from "@modelcontextprotocol/sdk/types.js"; @@ -35,35 +35,9 @@ export type TaskStatus = | "working" // The request is currently being processed | "input_required" // The task is waiting for input (e.g., elicitation or sampling) | "completed" // The request completed successfully and results are available - | "failed" // The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result has `isError` set to true. + | "failed" // The associated request failed due to a JSON-RPC error during execution | "cancelled"; // The request was cancelled before completion -/** - * Metadata for augmenting a request with task execution. - * Include this in the `task` field of the request parameters. - * - * @category `tasks` - */ -export interface TaskMetadata { - /** - * Requested duration in milliseconds to retain task from creation. - */ - ttl?: number; -} - -/** - * Metadata for associating messages with a task. - * Include this in the `_meta` field under the key `io.modelcontextprotocol/related-task`. - * - * @category `tasks` - */ -export interface RelatedTaskMetadata { - /** - * The task identifier this message is associated with. - */ - taskId: string; -} - /** * Data associated with a task. * @@ -76,13 +50,15 @@ export interface Task { taskId: string; /** - * Current task state. + * Current task status. */ status: TaskStatus; /** * Optional human-readable message describing the current task state. * This can provide context for any status, including: + * - Progress descriptions for "working" + * - Work blocked on "input_required" * - Reasons for "cancelled" status * - Summaries for "completed" status * - Diagnostic information for "failed" status (e.g., error details, what went wrong) @@ -100,26 +76,162 @@ export interface Task { lastUpdatedAt: string; /** - * Actual retention duration from creation in milliseconds, null for unlimited. + * Time-to-live duration from creation in integer milliseconds, null for unlimited. + * The server may discard the task after the TTL elapses. This value MAY change + * over the lifetime of a task. * @nullable */ - ttl: number | null; + ttlMs: number | null; + + /** + * Suggested polling interval in integer milliseconds. Clients SHOULD honor + * this value to avoid overwhelming the server. This value MAY change over + * the lifetime of a task. + */ + pollIntervalMs?: number; +} + +/* Detailed Task Variants */ + +/** + * A task that is in a normal working state. + * Used by tasks/get and notifications/tasks. + * + * @category `tasks` + */ +export interface WorkingTask extends Task { + status: "working"; +} + +/** + * A single input request from the server to the client during task execution. + * + * @category `tasks` + */ +// TODO: Import from SDK once updated for MRTR +export type InputRequest = + | CreateMessageRequest + | ListRootsRequest + | ElicitRequest; + +/** + * A single input response from the client to the server during task execution. + * + * @category `tasks` + */ +// TODO: Import from SDK once updated for MRTR +export type InputResponse = + | CreateMessageResult + | ListRootsResult + | ElicitResult; + +/** + * Outstanding server-to-client requests that need to be fulfilled during task execution. + * Keys are arbitrary identifiers for matching requests to responses. Each key MUST be + * unique over the lifetime of a single task. + * + * @category `tasks` + */ +// TODO: Import from SDK once updated for MRTR +export interface InputRequests { + [key: string]: InputRequest; +} + +/** + * Client responses to outstanding input requests. Each key MUST correspond to a + * currently-outstanding inputRequest key. + * + * @category `tasks` + */ +// TODO: Import from SDK once updated for MRTR +export interface InputResponses { + [key: string]: InputResponse; +} + +/** + * A task that is waiting for input from the client. + * Used by tasks/get and notifications/tasks. + * + * @category `tasks` + */ +export interface InputRequiredTask extends Task { + status: "input_required"; + + /** + * Server-to-client requests that need to be fulfilled during task execution. + * Keys are arbitrary identifiers for matching requests to responses. + */ + inputRequests: InputRequests; +} + +/** + * A task that has completed successfully. + * Used by tasks/get and notifications/tasks. + * + * @category `tasks` + */ +export interface CompletedTask extends Task { + status: "completed"; + + /** + * The final result of the task. + * The structure matches the result type of the original request. + * For example, a CallToolRequest task would return the CallToolResult structure. + */ + result: { [key: string]: unknown }; +} + +/** + * A task that has failed due to a JSON-RPC error during execution. + * Used by tasks/get and notifications/tasks. + * + * @category `tasks` + */ +export interface FailedTask extends Task { + status: "failed"; /** - * Suggested polling interval in milliseconds. + * The JSON-RPC error that caused the task to fail. */ - pollInterval?: number; + error: { [key: string]: unknown }; } /** - * A response to a task-augmented request. + * A task that has been cancelled. + * Used by tasks/get and notifications/tasks. * * @category `tasks` */ -export interface CreateTaskResult extends Result { - task: Task; +export interface CancelledTask extends Task { + status: "cancelled"; } +/** + * A union type representing a task with status-specific fields inlined. + * This type is used by tasks/get responses and notifications/tasks + * notifications to provide complete task state including terminal results + * or pending input requests. + * + * @category `tasks` + */ +export type DetailedTask = + | WorkingTask + | InputRequiredTask + | CompletedTask + | FailedTask + | CancelledTask; + +/* Task Creation */ + +/** + * The result returned by a server in lieu of a standard result shape when + * it elects to process a request asynchronously. The resultType field MUST + * be set to "task". This type is Result & Task (flat). + * + * @category `tasks` + */ +export type CreateTaskResult = Result & Task; + /* Task Operations */ /** @@ -138,37 +250,42 @@ export interface GetTaskRequest extends JSONRPCRequest { } /** - * The response to a tasks/get request. + * The response to a tasks/get request. Carries the appropriate DetailedTask + * variant for the task's current status. The resultType field MUST be set + * to "complete". * * @category `tasks/get` */ -export type GetTaskResult = Result & Task; +export type GetTaskResult = Result & DetailedTask; /** - * A request to retrieve the result of a completed task. + * A request to provide input responses to a task in the input_required state. * - * @category `tasks/result` + * @category `tasks/update` */ -export interface GetTaskPayloadRequest extends JSONRPCRequest { - method: "tasks/result"; +export interface UpdateTaskRequest extends JSONRPCRequest { + method: "tasks/update"; params: { /** - * The task identifier to retrieve results for. + * The task identifier to update. */ taskId: string; + + /** + * Responses to outstanding inputRequests previously surfaced by the server. + * Each key MUST correspond to a currently-outstanding inputRequest key. + */ + inputResponses: InputResponses; }; } /** - * The response to a tasks/result request. - * The structure matches the result type of the original request. - * For example, a tools/call task would return the CallToolResult structure. + * The response to a tasks/update request. An empty acknowledgement. + * The resultType field MUST be set to "complete". * - * @category `tasks/result` + * @category `tasks/update` */ -export interface GetTaskPayloadResult extends Result { - [key: string]: unknown; -} +export type UpdateTaskResult = Result; /** * A request to cancel a task. @@ -186,157 +303,72 @@ export interface CancelTaskRequest extends JSONRPCRequest { } /** - * The response to a tasks/cancel request. + * The response to a tasks/cancel request. An empty acknowledgement. + * Cancellation is cooperative and eventually consistent. + * The resultType field MUST be set to "complete". * * @category `tasks/cancel` */ -export type CancelTaskResult = Result & Task; - -/** - * A request to retrieve a list of tasks. - * - * @category `tasks/list` - */ -export interface ListTasksRequest extends PaginatedRequest { - method: "tasks/list"; -} - -/** - * The response to a tasks/list request. - * - * @category `tasks/list` - */ -export interface ListTasksResult extends PaginatedResult { - tasks: Task[]; -} +export type CancelTaskResult = Result; /* Task Notifications */ /** - * Parameters for a `notifications/tasks/status` notification. + * Parameters for a `notifications/tasks` notification. + * Carries a complete DetailedTask for the current status. * - * @category `notifications/tasks/status` + * @category `notifications/tasks` */ export type TaskStatusNotificationParams = NotificationParams & - Task & { [key: string]: unknown }; + DetailedTask & { [key: string]: unknown }; /** - * An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications. + * An optional notification from the server to the client, informing it that + * a task's status has changed. Servers are not required to send these notifications. + * Clients subscribe via subscriptions/listen. * - * @category `notifications/tasks/status` + * @category `notifications/tasks` */ export interface TaskStatusNotification extends JSONRPCNotification { - method: "notifications/tasks/status"; + method: "notifications/tasks"; params: TaskStatusNotificationParams; } -/* Task-Augmented Request Params */ +/* Subscription Additions */ /** - * Common params for any task-augmented request. - * Extends the base RequestParams to include an optional `task` field. + * Task-specific fields for the subscriptions/listen request. + * Clients include tasksStatus to subscribe to notifications/tasks + * for specific task IDs. * - * @category `tasks` + * @category `subscriptions` */ -export interface TaskAugmentedRequestParams extends RequestParams { +export interface TaskSubscriptionNotifications { /** - * If specified, the caller is requesting task-augmented execution for this request. - * The request will return a CreateTaskResult immediately, and the actual result can be - * retrieved later via tasks/result. - * - * Task augmentation is subject to capability negotiation - receivers MUST declare support - * for task augmentation of specific request types in their capabilities. + * Subscribe to notifications/tasks for specific task IDs. */ - task?: TaskMetadata; + taskIds?: string[]; } -/* Capability Additions */ - /** - * Task-related server capabilities. - * Include this in the server's `capabilities` object during initialization. + * Task-specific fields for the notifications/subscriptions/acknowledged notification. + * The server includes the list of task IDs it has agreed to send status notifications for. * - * @category `tasks` + * @category `subscriptions` */ -export interface TaskServerCapabilities { - tasks?: { - /** - * Whether this server supports tasks/list. - */ - list?: Record; - /** - * Whether this server supports tasks/cancel. - */ - cancel?: Record; - /** - * Specifies which request types can be augmented with tasks. - */ - requests?: { - /** - * Task support for tool-related requests. - */ - tools?: { - /** - * Whether the server supports task-augmented tools/call requests. - */ - call?: Record; - }; - }; - }; -} - -/** - * Task-related client capabilities. - * Include this in the client's `capabilities` object during initialization. - * - * @category `tasks` - */ -export interface TaskClientCapabilities { - tasks?: { - /** - * Whether this client supports tasks/list. - */ - list?: Record; - /** - * Whether this client supports tasks/cancel. - */ - cancel?: Record; - /** - * Specifies which request types can be augmented with tasks. - */ - requests?: { - /** - * Task support for sampling-related requests. - */ - sampling?: { - /** - * Whether the client supports task-augmented sampling/createMessage requests. - */ - createMessage?: Record; - }; - /** - * Task support for elicitation-related requests. - */ - elicitation?: { - /** - * Whether the client supports task-augmented elicitation/create requests. - */ - create?: Record; - }; - }; - }; +export interface TaskSubscriptionAcknowledgedNotifications { + /** + * Task IDs the server has agreed to send status notifications for. + */ + taskIds?: string[]; } -/* Tool-Level Task Support */ +/* Extension Capability */ /** - * Task support declaration for individual tools. - * Include this in the tool's definition returned by tools/list. - * - * - "forbidden": Tool does not support task-augmented execution (default when absent) - * - "optional": Tool may support task-augmented execution - * - "required": Tool requires task-augmented execution + * The extension capability declaration for the tasks extension. + * An empty object indicates support; no extension-specific settings are currently defined. * * @category `tasks` */ -export type ToolTaskSupport = "forbidden" | "optional" | "required"; +export type TasksExtensionCapability = Record; diff --git a/seps/2663-tasks-extension.md b/seps/2663-tasks-extension.md new file mode 100644 index 0000000..9f9012f --- /dev/null +++ b/seps/2663-tasks-extension.md @@ -0,0 +1,964 @@ +# SEP-2663: Tasks Extension + +- **Status**: Final +- **Type**: Extensions Track +- **Created**: 2026-04-27 +- **Author(s)**: Luca Chang (@LucaButBoring), Caitie McCaffrey (@CaitieM20); on behalf of the Agents Working Group +- **Sponsor**: Caitie McCaffrey (@CaitieM20) +- **Extension Identifier**: `io.modelcontextprotocol/tasks` +- **PR**: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663 + +## Abstract + +This SEP defines an extension that allows a server to respond to a `tools/call` request with an asynchronous _task handle_ instead of a final result, allowing the client to retrieve the eventual result by polling. The extension introduces three methods: `tasks/get`, `tasks/update`, and `tasks/cancel`; a polymorphic-result discriminator (`resultType: "task"`); and a `Task` shape that carries a task status, in-progress server-to-client requests, and a final result or error. Task creation is server-directed: the client signals support by including the extension in its per-request capabilities, and the server decides on a per-request basis whether to materialize a task. + +Tasks will become a foundational building block of MCP and are expected to be supported in future protocol versions. The experimental `tasks` feature in the `2025-11-25` specification served as a stopgap until the protocol's extension mechanism was available. Now that [extensions](https://modelcontextprotocol.io/extensions/overview) have been [formalized](https://modelcontextprotocol.io/seps/2133-extensions), moving tasks to an official extension gives the feature time to incubate and evolve based on additional real-world implementation feedback, without being constrained by the core specification's release cadence. Once the extension has stabilized and achieved broad adoption, it is intended to be promoted into the core protocol. + +This proposal _removes_ the version of [tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks) specified in the `2025-11-25` release from the core protocol and moves it to an Extension. It also proposes updates to Tasks shaped by implementation feedback since that release, and by several changes to the base protocol included in the `2026-06-30` specification: + +- [SEP-2260: Require Server requests to be associated with a Client request](https://modelcontextprotocol.io/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests) +- [SEP-2322: Multi Round-Trip Requests](https://modelcontextprotocol.io/seps/2322-MRTR) +- [SEP-2243: HTTP Header Standardization for Streamable HTTP Transport](https://modelcontextprotocol.io/seps/2243-http-standardization) +- [SEP-2567: Sessionless MCP via Explicit State Handles](https://modelcontextprotocol.io/seps/2567-sessionless-mcp) +- [SEP-2575: Make MCP Stateless](https://modelcontextprotocol.io/seps/2575-stateless-mcp) + +## Motivation + +The experimental [tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks) feature served as an alternate execution mode for tool calls, elicitation, and sampling, allowing receivers to return a poll handle instead of blocking until a final result was ready. Implementation experience surfaced several challenges: + +1. **The handshake is fragile.** Tasks today expose method-level capabilities (`tasks.requests.tools.call` declares that `tools/call` **MAY** be task-augmented) alongside a tool-level `execution.taskSupport` field that declares whether a particular tool will accept the augmentation. Clients express their own support for tasks by passing a `task` parameter on their requests, but **MUST NOT** include it if the method/tool does not support tasks. A client that wants to opt into tasks must therefore prime its state with a `tools/list` call before issuing any task-augmented request, and cannot blindly attach a `task` parameter to every request to handle tools isomorphically. This is confusing, implicit, and easy to get wrong. + +2. **`tasks/result` is a blocking trap.** In the current flow, a client that observes `input_required` is required to call `tasks/result` prematurely so that the server has an SSE stream on which to side-channel elicitation or sampling requests. `tasks/result` then blocks until the entire operation completes. This forces long-lived persistent connections that many clients and servers do not want to implement, and it conflicts with [SEP-2260](https://modelcontextprotocol.io/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests), which disallows unsolicited server-to-client requests outright. Under SEP-2260, the SSE semantics that justified the blocking behavior no longer apply. + +3. **`tasks/list` scoping cannot be defined.** To avoid clients cancelling or retrieving results for tasks they shouldn't have access to, all tasks should be bound to some sort of "authorization context," the implementation of which is left to individual servers according to their existing bespoke permission models. However, in many cases, it is not possible to perform this binding, in which case the task ID becomes the only line of defense against contamination. In this scenario, it is unsafe for a server to support `tasks/list` at all. While it was possible for tasks to instead be bound to a session, [SEP-2567](https://modelcontextprotocol.io/seps/2567-sessionless-mcp) removes sessions from the protocol. There is no other natural scope a server can define unilaterally — task IDs can be unguessable handles that a server can recognize one at a time, but servers cannot reliably correlate two unrelated handles to the same caller without additional state. + +Beyond implementation challenges, tasks face another structural issue: **Client-hosted tasks are no longer expressible.** [SEP-1686](./1686-tasks.md) permitted clients to host tasks for elicitation and sampling, in part to avoid coupling tasks to tool calls. [SEP-2260](https://modelcontextprotocol.io/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests) makes any unsolicited server-to-client request invalid; every server-to-client polling request under client-hosted tasks would be unsolicited by definition. + +This proposal intends to solve the above issues by redesigning certain aspects of the feature and moving tasks out to an official extension. Redefining tasks as an official extension gives the feature more time to incubate and evolve independently of the core specification, promoting adoption. As part of the redesign, this proposal consolidates the polling lifecycle into `tasks/get` and a new `tasks/update` to remove the blocking `tasks/result` method. The redesign allows servers to return tasks unsolicited (in response to ordinary, non-`task`-flagged requests) to eliminate the per-request opt-in and the `tools/list` warmup, relying instead on the extension capability as the single handshake point. Finally, this proposal removes client-hosted elicitation and sampling tasks in compliance with [SEP-2260](https://modelcontextprotocol.io/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests). + +## Specification + +The MCP Tasks extension allows certain requests to be augmented with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they augment, and are intended for client polling and deferred result retrieval. Each task is uniquely identifiable by a server-generated **task ID**. + +Tasks are useful for representing expensive computations and batch processing requests, and map naturally onto external job APIs. + +### Extension Identifier + +This extension is identified as: `io.modelcontextprotocol/tasks`. + +### Capability Negotiation + +The client and server declare support for the tasks extension in their respective capabilities objects (using updated form from [SEP-2575: Make MCP Stateless](https://modelcontextprotocol.io/seps/2575-stateless-mcp)): + +```jsonc +// Client to server, in per-request capabilities +{ + // Other request parameters... + "params": { + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, + }, +} +``` + +```jsonc +// Server to client, in response to server/discover +{ + "result": { + // Other response parameters... + "capabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, +} +``` + +No extension-specific settings are currently defined; an empty object indicates support. + +A server that has negotiated this extension **MAY** return `CreateTaskResult` in lieu of a standard result (e.g. `CallToolResult`) in response to any supported request at its own discretion and on a per-request basis. The server is the sole decider; clients do not signal task preference on the request itself. The client declaring the extension capability does not suggest that it requires a `CreateTaskResult` in response to that request. + +A server **MUST NOT** return `CreateTaskResult` to a client that did not include the extension capability on its request, regardless of prior declarations. A client that has negotiated this extension **MUST** be prepared to handle either `CallToolResult` or `CreateTaskResult` in response to any supported request it issues. A client that receives `CreateTaskResult` in response to an unsupported request type **MUST** interpret this as an invalid response to the request. + +If a server is unable to service a request to a client that does not declare this extension capability without returning `CreateTaskResult`, the server **MUST** return an error with the code `-32003` (Missing Required Client Capability), indicating the required extension in the error response: + +```jsonl +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + // MISSING_REQUIRED_CLIENT_CAPABILITY + "code": -32003, + // Message provided for example purposes only. The content of this example message is non-normative. + "message": "Missing required client capability", + "data": { + "requiredCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {} + } + } + } + } +} +``` + +### Supported Methods + +The following methods currently support task-augmented execution: + +- `tools/call` + +This specification may be extended to support tasks over other request types in the future; implementations **SHOULD** be designed to accommodate additional request types in future revisions of this specification. + +### Polymorphic Results + +A request that is eligible for task-augmentation may return one of two distinct result shapes — the request's standard result, or a `CreateTaskResult`. The discriminator is the `resultType` field on the result object, introduced by [SEP-2322](https://modelcontextprotocol.io/seps/2322-MRTR): + +```typescript +// "task" is introduced by this extension. +type ResultType = "complete" | "input_required" | "task"; +``` + +Servers **MUST** set `resultType` to `"task"` when returning a `CreateTaskResult` so that clients can distinguish it from a standard result. Servers **MUST NOT** set `resultType` to `"task"` on result types other than `CreateTaskResult`. + +Client implementors are advised that existing code returning a fixed shape (e.g., a `tools/call` method returning `CallToolResult`) need not change their public contract — they can transparently drive the polling flow internally and surface only the final, completed result. New implementation surfaces **MAY** expose the task lifecycle directly for applications able to leverage it. + +### Tasks + +A `Task` carries operational metadata about ongoing work. + +```typescript +interface Task { + /** Stable identifier for this task. */ + taskId: string; + + /** Current task status. */ + status: "working" | "input_required" | "completed" | "cancelled" | "failed"; + + /** + * Optional message describing the current task state. + * This can provide context for any status, for example (non-normative): + * - Progress descriptions for "working" + * - Work blocked on "input_required" + * - Reasons for "cancelled" status + * - Summaries for "completed" status + * - Additional information for "failed" status (e.g., error details, what went wrong) + * + * This MAY be exposed to the end-user or model. + */ + statusMessage?: string; + + /** ISO 8601 timestamp when the task was created. */ + createdAt: string; + + /** ISO 8601 timestamp when the task was last updated. */ + lastUpdatedAt: string; + + /** + * Time-to-live duration from creation in integer milliseconds, null for unlimited. + * The server may discard the task after the TTL elapses. This value MAY change + * over the lifetime of a task. + */ + ttlMs: number | null; + + /** + * Suggested polling interval in integer milliseconds. Clients SHOULD honor + * this value to avoid overwhelming the server. This value MAY change over + * the lifetime of a task. + */ + pollIntervalMs?: number; +} +``` + +#### Task Status + +Tasks can be in one of the following states: + +- `working`: The request is currently being processed. +- `input_required`: The server needs input from the client before the task can proceed. The `tasks/get` response will include outstanding requests in the `inputRequests` field. The client **MUST** inspect this field and **SHOULD** provide responses via the `inputResponses` field in subsequent `tasks/update` requests. +- `completed`: The request completed successfully and results are available in the `result` field. This includes tool calls that returned results with `isError: true`. +- `failed`: The request failed due to a JSON-RPC error during execution. The task will include the `error` field with the JSON-RPC error details. This status **MUST NOT** be used for non-JSON-RPC errors. +- `cancelled`: The request was cancelled before completion. + +Derived shapes of `Task` inline status-specific payload fields and are used by `tasks/get` responses and `notifications/tasks` notifications: + +```ts +/** + * A task that is in a normal working state. + * Used by tasks/get and notifications/tasks. + */ +export interface WorkingTask extends Task { + status: "working"; +} + +/** + * A task that is waiting for input from the client. + * Used by tasks/get and notifications/tasks. + */ +export interface InputRequiredTask extends Task { + status: "input_required"; + /** + * Server-to-client requests that need to be fulfilled during task execution. + * Keys are arbitrary identifiers for matching requests to responses. + */ + inputRequests: InputRequests; +} + +/** + * A task that has completed successfully. + * Used by tasks/get and notifications/tasks. + */ +export interface CompletedTask extends Task { + status: "completed"; + /** + * The final result of the task. + * The structure matches the result type of the original request. + * For example, a CallToolRequest task would return the CallToolResult structure. + */ + result: JSONObject; +} + +/** + * A task that has failed due to a JSON-RPC error. + * Used by tasks/get and notifications/tasks. + */ +export interface FailedTask extends Task { + status: "failed"; + /** + * The JSON-RPC error that caused the task to fail. + */ + error: JSONObject; +} + +/** + * A task that has been cancelled. + * Used by tasks/get and notifications/tasks. + */ +export interface CancelledTask extends Task { + status: "cancelled"; +} + +/** + * A union type representing a task with optional inlined result/error/inputRequests fields. + * This type is used by tasks/get and notifications/tasks to provide complete task state + * including terminal results or pending input requests. + */ +export type DetailedTask = + | WorkingTask + | InputRequiredTask + | CompletedTask + | FailedTask + | CancelledTask; +``` + +### Task Creation + +A server returns `CreateTaskResult` in lieu of the standard result shape for a request to indicate that request will be processed asynchronously. + +```typescript +// resultType: "task" +type CreateTaskResult = Result & Task; +``` + +**Example Request (CallToolRequest):** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tools/call", + "params": { + "name": "get_weather", + "arguments": { + "city": "New York" + } + } +} +``` + +**Example Response (CreateTaskResult):** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "statusMessage": "The operation is now in progress.", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:40:00Z", + "ttlMs": 60000, + "pollIntervalMs": 5000 + } +} +``` + +The embedded `task` is the seed state for the task, typically (though not necessarily) with `status: "working"`. The client uses `task.taskId` for all subsequent `tasks/get`, `tasks/update`, and `tasks/cancel` calls. + +A server **MUST NOT** return `CreateTaskResult` until the task is durably created — that is, until a `tasks/get` for the returned `taskId` would resolve. In eventually-consistent environments, the server **MUST** wait for consistency before responding. This requirement eliminates the need for clients to speculatively poll for task creation. + +Server implementations that use multi round-trip requests in conjunction with task creation (for example, a tool that requires elicitation over `InputRequiredResult` before creating a task) **SHOULD** resolve all MRTR exchanges _synchronously_ before responding with a `CreateTaskResult`. + +### Task Polling + +Clients poll for task completion by sending `tasks/get` requests. + +Clients **SHOULD** respect the `pollIntervalMs` provided in responses when determining polling frequency. The `pollIntervalMs` **MAY** change over the lifetime of a task. Servers **MAY** rate-limit clients polling more frequently than the recorded `pollIntervalMs`. + +Clients **SHOULD** continue polling until the task reaches a terminal status or until invoking `tasks/cancel`. Clients **SHOULD** persist task IDs to durable storage so that polling can resume after a crash or restart. + +#### Request + +```typescript +interface GetTaskRequest extends JSONRPCRequest { + method: "tasks/get"; + params: { + /** Identifier of the task to query. */ + taskId: string; + }; +} +``` + +#### Response + +Upon receiving a `tasks/get` request, the server **MUST** check the status of the task and respond accordingly: + +1. If the status is `working`, the server **MUST** return a a `Task` object with status `working`. +2. If the status is `input_required`, the server **MUST** return a `Task` object with status `input_required` and an `inputRequests` field defined in [Multi Round-Trip Requests](https://modelcontextprotocol.io/specification/draft/basic/utilities/mrtr). The `inputRequests` field **MUST** contain all outstanding requests from the server to the client that need to be fulfilled before the task can proceed. +3. If the status is `completed`, the server **MUST** return a `Task` object with status `completed` and a `result` field containing the final result of the task. +4. If the status is `cancelled`, the server **MUST** return a `Task` object with status `cancelled`. +5. If the status is `failed`, the server **MUST** return a `Task` object with status `failed` and the error that occurred during execution. + +```typescript +type GetTaskResult = Result & DetailedTask; +``` + +The response carries the appropriate response variant for the task's current status (see [Task Status](#task-status)). The `resultType` field **MUST** be set to `"complete"` on this object as it is the standard result shape for the `tasks/get` request. + +If the task has a non-null `ttlMs`, clients **MAY** treat the TTL as a backstop: if the task's observable status has not reflected the update after `createdAt` plus `ttlMs` has elapsed, the client **MAY** consider the task to no longer be usable. Conversely, servers **MAY** mark a task as `failed` at any point after the TTL elapses, and subsequently delete it at any time. The value of `ttlMs` **MAY** change over the lifetime of a task. + +### Task Update Requests + +When a task requires input from the client (indicated by the `input_required` status), the server includes outstanding requests in the `inputRequests` field of the `tasks/get` response (see [Multi Round-Trip Requests](https://modelcontextprotocol.io/specification/draft/basic/utilities/mrtr)). The client provides responses via the `inputResponses` field in one or more subsequent `tasks/update` requests. + +When a client observes a `tasks/get` response (or `notifications/tasks` notification) with `status: "input_required"`, the client **SHOULD** fulfill the outstanding requests in `inputRequests` by sending one or more `tasks/update` requests with corresponding `inputResponses`. After sending a `tasks/update`, the client **SHOULD** continue observing the task's status via polling (`tasks/get`) or notifications (`notifications/tasks`) until it reaches a terminal state. + +Clients **MUST** treat each entry in `inputRequests` as they would the equivalent standalone server-to-client request — for example, an elicitation request surfaced via `inputRequests` is subject to the same trust model and user-facing behavior as a direct `elicitation/create` request. Clients **SHOULD** deduplicate `inputRequests` keys across consecutive polls to avoid presenting the same request to the user or model more than once. + +Each request key in `inputRequests` **MUST** be unique over the lifetime of a single task. A server **MUST NOT** reuse a key for a subsequent server-to-client request after a response for that key has been delivered, and **MUST NOT** use the same key to refer to two distinct requests over a task's lifetime. This guarantees that `inputResponses` keyed by the same identifier always refer to the request the client expects, eliminates ambiguity for clients deduplicating across polls, and lets servers ignore `inputResponses` for unknown or already-satisfied requests. + +#### Request + +```typescript +interface UpdateTaskRequest extends JSONRPCRequest { + method: "tasks/update"; + params: { + /** Identifier of the task to update. */ + taskId: string; + + /** + * Responses to outstanding inputRequests previously surfaced by the + * server. Shape per MRTR. Each key MUST correspond to a currently- + * outstanding inputRequest key. + */ + inputResponses: InputResponses; + }; +} +``` + +#### Response + +```typescript +type UpdateTaskResult = Result; // empty acknowledgement +``` + +On success, the server **MUST** acknowledge the request with an empty result. The acknowledgement is _eventually consistent_: the server **MAY** accept the responses and return the ack before the task's observable status (via `tasks/get` or `notifications/tasks`) reflects them. Servers **SHOULD** return a JSON-RPC error if the `taskId` does not correspond to a known task. Clients **SHOULD** track `inputRequests` keys to avoid responding to requests more than once. + +A server **SHOULD** ignore any `inputResponses` responses mapped to a key that is not currently outstanding for the task — including keys that were never issued, keys that have already been answered, and keys whose corresponding request has been superseded. A server **MAY** accept a partial set of responses (a strict subset of currently-outstanding keys); + +The `resultType` field **MUST** be set to `"complete"` on `UpdateTaskResult` as it is the standard result shape for the `tasks/update` request. + +### Task Cancellation + +A client sends a `tasks/cancel` request to signal its intent to cancel an in-progress task. The `notifications/cancelled` notification **MUST NOT** be used for task cancellation. + +#### Request + +```typescript +interface CancelTaskRequest extends JSONRPCRequest { + method: "tasks/cancel"; + params: { + taskId: string; + }; +} +``` + +#### Response + +```typescript +type CancelTaskResult = Result; // empty acknowledgement +``` + +The server **MUST** acknowledge the request with an empty result. Servers **SHOULD** return a JSON-RPC error if the `taskId` does not correspond to a known task. Cancellation processing is _eventually consistent_ — the task's observable status **MAY** remain `working` (or some other non-terminal status) after the ack, and **MAY** ultimately reach a terminal status other than `cancelled` if the work finished before cancellation could take effect. + +Cancellation is **cooperative**: The request signals intent, and the server decides whether and when to honor it. A server is not obligated to actually stop the work; it is only obligated to acknowledge the request. Eventual transition to `cancelled` is not guaranteed. + +Clients **MAY** delete all state associated with the task as soon as they send a cancellation (e.g., it no longer needs to retain the list of `inputRequests` keys that it has already responded to). The client does not need to poll `tasks/get` again to wait for the task to reach the `cancelled` state. + +The `resultType` field **MUST** be set to `"complete"` on `CancelTaskResult` as it is the standard result shape for the `tasks/cancel` request. + +### Task Status Notifications + +Servers **MAY** push status updates via `notifications/tasks` notifications in addition to servicing client polls: + +```typescript +export type TaskStatusNotificationParams = NotificationParams & Task; + +export interface TaskStatusNotification extends JSONRPCNotification { + method: "notifications/tasks"; + params: TaskStatusNotificationParams; +} +``` + +To begin listening for task status notifications, clients send a `subscriptions/listen` request to the server including a list of task IDs the client is interested in (see [SEP-2575](https://modelcontextprotocol.io/seps/2575-stateless-mcp)): + +```typescript +export interface SubscriptionsListenRequest extends Request { + method: "subscriptions/listen"; + params: { + // Other existing fields... + notifications: { + taskIds?: string[]; + // Other existing fields... + }; + }; +} +``` + +In its acknowledgement notification, the server includes the list of task IDs it has agreed to send task status notifications for, if any: + +```typescript +export interface SubscriptionsAcknowledgedNotification extends Notification { + method: "notifications/subscriptions/acknowledged"; + params: { + notifications: { + /** + * Subscribe to notifications/tasks for specific task IDs. + */ + taskIds?: string[]; + // Other existing fields... + }; + }; +} +``` + +If a client requests task status notifications but does not declare the `io.modelcontextprotocol/tasks` extension capability, the server **MUST** return a JSON-RPC error specifying the missing capabilities: + +```jsonl +{ + "jsonrpc": "2.0", + "id": 12, + "error": { + // MISSING_REQUIRED_CLIENT_CAPABILITY + "code": -32003, + // Message provided for example purposes only. The content of this example message is non-normative. + "message": "Missing required client capability", + "data": { + "requiredCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {} + } + } + } + } +} +``` + +Each notification carries a complete `DetailedTask` for the current status, identical to what `tasks/get` would have returned at that moment. + +**Notification:** + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/tasks", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "completed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 60000, + "pollIntervalMs": 5000, + "result": { + "content": [ + { + "type": "text", + "text": "Operation completed successfully." + } + ], + "isError": false + } + } +} +``` + +The notification includes the full task object, allowing clients to access the complete task state and final results without polling the `tasks/get` method. Clients **MAY** continue polling `tasks/get` in addition to subscribing to task status notifications, but need not do so. + +`notifications/progress` and `notifications/message` notifications **MUST NOT** be sent on the `subscriptions/listen` stream for a task, and are not supported on tasks in general in this specification. + +### Streamable HTTP: Routing Headers + +When `tasks/get`, `tasks/update`, or `tasks/cancel` is sent over the Streamable HTTP transport, the client **MUST** set the `Mcp-Name` header (defined by [SEP-2243](https://modelcontextprotocol.io/seps/2243-http-standardization)) to the value of `params.taskId`. This allows transport intermediaries and load balancers to route subsequent requests for the same task to the server instance holding its state, which is typically required for correctness. The `Mcp-Method` header is set to the JSON-RPC method name per [SEP-2243](https://modelcontextprotocol.io/seps/2243-http-standardization). + +### Example Message Flow + +Consider a simple tool call, `hello_world`, requiring an elicitation for the user to provide their name. The tool itself takes no arguments. + +To invoke this tool, the client makes a `CallToolRequest` as follows: + +```jsonc +{ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": { + "name": "hello_world", + "arguments": {}, + "_meta": { + // Other metadata... + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { + "io.modelcontextprotocol/tasks": {}, + }, + }, + }, + }, +} +``` + +The server determines (via bespoke logic) that it wants to create a task to represent this work, and it immediately returns a `CreateTaskResult`: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 + } +} +``` + +Once the client receives the `CreateTaskResult`, it begins polling `tasks/get`: + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +On each request while the task is in a `"working"` status, the server returns a regular task response: + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 + } +} +``` + +Eventually, the server reaches the point at which it needs to send an elicitation to the user. It sets the task status to `"input_required"` to signal this. On the next `tasks/get` request from the client, the server sends the elicitation payload via the `inputRequests` field. Note that while task `inputRequests` share structural similarities with [SEP-2322](https://modelcontextprotocol.io/seps/2322-MRTR) multi round-trip requests, they are a distinct mechanism: task `inputRequests` are surfaced via `tasks/get` and fulfilled via `tasks/update`, not via retries of the original method. A server that needs client input _before_ returning a `CreateTaskResult` (e.g. to decide whether to proceed) uses the multi round-trip request flow on the original request; a server that needs client input _during_ task execution uses the `inputRequests`/`inputResponses` mechanism described here. + +```json +{ + "jsonrpc": "2.0", + "id": 4, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +```json +{ + "id": 4, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "input_required", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "inputRequests": { + "name": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Please enter your name.", + "requestedSchema": { + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + } + } + } + } + } +} +``` + +For thoroughness, let's consider a case where the client happens to poll `tasks/get` again _before_ the user has fulfilled the elicitation request. As `inputRequests` is effectively a point-in-time snapshot of all outstanding server-to-client requests associated with the task, the server includes the same request again, despite the client having already seen this information (the client is advised to deduplicate `inputRequests` with the same key for UX purposes): + +```json +{ + "jsonrpc": "2.0", + "id": 5, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +```json +{ + "id": 5, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "input_required", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "inputRequests": { + "name": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Please enter your name.", + "requestedSchema": { + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + } + } + } + } + } +} +``` + +The user enters their name, and the client makes a `tasks/update` request with the satisfied information: + +```json +{ + "jsonrpc": "2.0", + "id": 6, + "method": "tasks/update", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "inputResponses": { + "name": { + "action": "accept", + "content": { + "input": "Luca" + } + } + } + } +} +``` + +The server acknowledges the request: + +```json +{ + "jsonrpc": "2.0", + "id": 6, + "result": { + "resultType": "complete" + } +} +``` + +Asynchronously, the server processes it and moves the task back into the `working` status: + +```json +{ + "jsonrpc": "2.0", + "id": 7, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +```json +{ + "id": 7, + "jsonrpc": "2.0", + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000 + } +} +``` + +Eventually, the server completes the request, so it stores the final `CallToolResult` and moves the task into the `"completed"` status. On the next `tasks/get` request, the server sends the final tool result inlined into the task object: + +```json +{ + "jsonrpc": "2.0", + "id": 8, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +```json +{ + "jsonrpc": "2.0", + "id": 8, + "result": { + "resultType": "complete", + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "completed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:50:00Z", + "ttlMs": 3600000, + "pollIntervalMs": 5000, + "result": { + "content": [ + { + "type": "text", + "text": "Hello, Luca!" + } + ], + "isError": false + } + } +} +``` + +### Error Handling + +Tasks use two error reporting mechanisms: + +1. **Protocol Errors**: Standard JSON-RPC errors for protocol-level issues +2. **Task Execution Errors**: Errors in the underlying request execution, reported through task status + +#### Protocol Errors + +Servers **MUST** return standard JSON-RPC errors for the following protocol error cases: + +- Invalid or nonexistent `taskId`: `-32602` (Invalid params) + - Servers **MUST** return this error for `tasks/get`. + - Servers **SHOULD** return this error for `tasks/update` and `tasks/cancel`. +- Internal errors: `-32603` (Internal error) + +Servers **SHOULD** provide informative error messages to describe the cause of errors. + +**Example: Task not found** + +```json +{ + "jsonrpc": "2.0", + "id": 70, + "error": { + "code": -32602, + "message": "Failed to retrieve task: Task not found" + } +} +``` + +**Example: Task expired** + +```json +{ + "jsonrpc": "2.0", + "id": 71, + "error": { + "code": -32602, + "message": "Failed to retrieve task: Task has expired" + } +} +``` + +Servers are not required to retain tasks indefinitely. It is compliant behavior for a server to return an error stating the task cannot be found if it has purged an expired task. + +#### Task Execution Errors + +When the underlying request encounters a JSON-RPC protocol error during execution, the task moves to the `failed` status. The `tasks/get` response **SHOULD** include a `statusMessage` field with diagnostic information about the failure, and **MUST** include the `error` field with the JSON-RPC error. + +The `failed` status **MUST NOT** be used to represent non-JSON-RPC errors, such as a tool result that completed with `isError: true`. Errors within the context of a protocol method result **MUST** use the `completed` status with the error details in the `result` field. This maintains a strong separation between protocol-level faults (which use the `failed` status) and other faults. + +**Example: Task with JSON-RPC execution error** + +```json +{ + "jsonrpc": "2.0", + "id": 4, + "result": { + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f820fe840", + "status": "failed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:40:00Z", + "ttlMs": 3600000, + "statusMessage": "Tool execution failed: API rate limit exceeded", + "error": { + "code": -32603, + "message": "API rate limit exceeded" + } + } +} +``` + +**Example: Tool call completed with tool error (isError: true)** + +For tool calls that complete successfully at the protocol level but return an tool-level error (indicated by `isError: true` in the tool result), the task reaches `completed` status with the tool result in the `result` field: + +```json +{ + "jsonrpc": "2.0", + "id": 5, + "result": { + "resultType": "task", + "taskId": "786512e2-9e0d-44bd-8f29-789f820fe840", + "status": "completed", + "createdAt": "2025-11-25T10:30:00Z", + "lastUpdatedAt": "2025-11-25T10:40:00Z", + "ttlMs": 3600000, + "result": { + "content": [ + { + "type": "text", + "text": "Failed to process request: invalid input" + } + ], + "isError": true + } + } +} +``` + +The `tasks/get` endpoint returns exactly what the underlying request would have returned: + +- If the underlying request resulted in a JSON-RPC error, the task uses `failed` status and the `error` field **MUST** contain that JSON-RPC error. +- If the request completed with a result (even if `isError: true` for tool results), the task uses `completed` status and the `result` field **MUST** contain that result. + +### Reservations + +- The `tasks/` method prefix and `notifications/tasks/` notification prefix are reserved for this extension. +- The result-discriminator value `"task"` for `resultType` is reserved for this extension. +- The label `io.modelcontextprotocol/tasks` is reserved for this extension. + +## Rationale + +### Unsolicited Tasks vs. Immediate Results + +An [alternative proposal](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1905) would have handled the immediate result case individually, and with slightly different preconditions: _If_ tasks are supported, _and_ the client supports immediate task results, _then_ servers may return a regular result in response to a task-augmented request. That version of immediate results looked like a better option at the time, as it implied no breaking changes on top of the initial tasks specification. + +However, as we look to [move away](https://blog.modelcontextprotocol.io/posts/2025-12-19-mcp-transport-future/) from stateful protocol interactions and given the current experimental state of tasks in general, it seems worth proposing a somewhat more radical change that reduces the complexity of the overall specification and makes tasks more "native" to MCP at this time. In particular, the choice to allow unsolicited tasks (in _addition_ to immediate results) means promoting tasks to a first-class concept intended for all persistent operations, as opposed to being a parallel and somewhat specialized concept. + +This happens to align with the proposed [SEP-2322](https://modelcontextprotocol.io/seps/2322-MRTR), but the two are not coupled with one another. + +### Splitting Reads (`tasks/get`) and Writes (`tasks/update`) + +Earlier drafts of this redesign let `tasks/get` carry `inputResponses` so a single round trip would both submit responses and observe the resulting state. That conflation has costs: it makes the read path non-idempotent (a retried `tasks/get` could re-submit responses), it forces the read path to share the eventual-consistency model of the write, and it complicates intermediaries that want to cache or deduplicate reads. Splitting the methods leaves `tasks/get` as a pure, idempotent read that any layer can cache or replay safely, and confines write semantics — including their eventual-consistency window — to `tasks/update`. + +`tasks/update`'s ack-only response shape follows from the same separation: there is no read data the server needs to return that the client cannot get from a follow-up `tasks/get`, and forcing an embedded `Task` into the response would re-introduce the non-idempotency we are trying to avoid. The cost is one extra round-trip per round of input — paid only when the task actually requires a client request. + +### Task Creation Consistency + +The following new requirement is introduced: + +> A server **MUST NOT** return `CreateTaskResult` until the task is durably created — that is, until a `tasks/get` for the returned `taskId` would resolve. In eventually-consistent environments, the server **MUST** wait for consistency before responding. This requirement eliminates the need for clients to speculatively poll for task creation. + +Unlike `tasks/update` and `tasks/cancel`, task creation is strongly-consistent. This has to be the case to avoid speculative `tasks/get` requests from requestors that would otherwise not know if a task has silently been dropped or if it simply has not been created yet. Conversely, eventual consistency in `tasks/update` and `tasks/cancel` works because the client behavior is not contingent on the results of those operations (the client can continue to poll either way). While consistent task creation does increase latency costs in distributed systems that did not already behave this way, explicitly introducing this requirement simplifies client implementations and eliminates a source of undefined behavior. + +This also aligns with long-running operation APIs in general, which typically require that once an operation is acknowledged, it must be findable via the polling endpoint. + +### Ack-only Cancellation + +In the `2025-11-25` design of tasks, `tasks/cancel` returned a task describing the task's state immediately after the cancellation attempt. That return shape implies a synchronous read — the server must consult task state to populate it — but cancellation is inherently asynchronous in many applications (a separate worker decides whether and when to honor it), so the returned task object would in many cases simply repeat what the next `tasks/get` would show. Reducing `tasks/cancel` to an ack matches the operation's actual semantics: The request is a signal, not a state query. Clients that want to know the post-cancel status do so via `tasks/get` on the same code path they use for all other state observation. + +The eventual-consistency on the ack is the same separation as for `tasks/update`: The server may record the cancellation request and respond before the worker has actually transitioned the task, without allowing the client to interpret the ack as strongly-consistent. + +While `tasks/update` and `tasks/cancel` use ack-only response shapes for the reasons above, servers **SHOULD** still return errors for clearly invalid requests — such as an unknown `taskId`. The ack-only design is about avoiding synchronous reads of task state in the success path, not about suppressing errors that the server can detect at request time. Returning errors for invalid inputs gives clients a faster signal that something is wrong, rather than forcing them to discover the problem indirectly through subsequent `tasks/get` polls. + +### Composition with Multi Round-Trip Requests + +The following new requirement is introduced: + +> Server implementations that use multi round-trip requests in conjunction with task creation (for example, a tool that requires elicitation over `InputRequiredResult` before creating a task) **SHOULD** resolve all MRTR exchanges _synchronously_ before responding with a `CreateTaskResult`. + +A `tools/call` that supports both MRTR ([SEP-2322](https://modelcontextprotocol.io/seps/2322-MRTR)) and this extension may use them sequentially by sending one or more `InputRequiredResult` exchanges to gather input synchronously, followed by a `CreateTaskResult` to hand off to asynchronous execution. This composition is a consequence of the `resultType` discriminator — each response is independently typed and the client switches behavior based on the value it receives, _without_ maintaining any state between the two modes. Prohibiting this would require imposing an artificial constraint with no protocol-level mechanism to enforce it, since the client is unaware that the server will create a task ahead of time. + +The two flows maintain separate state despite sharing field names. The MRTR phase ends when the server returns any non-`"input_required"` `resultType`, at which point its `inputRequests` keys are consumed. The task phase begins with `CreateTaskResult` and maintains _its own_ `inputRequests` keys independently. Key uniqueness for task `inputRequests` is scoped to the lifetime of the task and does not extend to keys from the preceding MRTR phase. Clients do not need to deduplicate across the two flows. + +## Backward Compatibility + +The experimental tasks feature in the `2025-11-25` release is **not wire-compatible** with this extension. Specifically: + +- `tasks/result` is removed. Clients calling `tasks/result` against a server with this extension in the `2026-06-30` specification **MUST** receive `-32601` (Method Not Found). +- The `task` parameter on `CallToolRequest` is removed. Servers receiving requests with a `task` parameter under this extension in the `2026-06-30` specification **MUST** ignore it (treat the field as unknown) rather than using it as an opt-in. +- The `tasks.requests.*` and `tasks.cancel`/`tasks.list` capability declarations are not part of this extension. A server that previously advertised these **MUST** migrate to declaring `io.modelcontextprotocol/tasks` as of the `2026-06-30` specification and **MUST NOT** continue to advertise the legacy capabilities under any protocol version that includes this extension. + +Implementations that need to bridge legacy clients can shim at the SDK level: a server can implement both the experimental and extension surfaces in parallel, dispatching based on which capability and protocol version the client negotiated. + +A server that returns the standard `CallToolResult` shape — i.e., never elects to create a task — remains fully spec-compliant under this extension. Clients that have negotiated the extension **MUST** handle both result shapes for any augmented request. + +## Security Implications + +- **Task ID unguessability.** A server **MAY** use task IDs as bearer tokens for a server's stored state. Servers **MUST** generate them with sufficient entropy that a third party cannot enumerate or guess them. +- **Auth binding.** Servers **MUST** perform authentication and authorization checks on each task-related request to ensure that the client has permission to access a task. +- **Cross-caller correlation.** Because there is no `tasks/list`, a server cannot inadvertently leak the existence of one caller's tasks to another. This is an improvement over the `2025-11-25` tasks specification, in which a poorly-scoped list could expose unrelated task IDs. +- **Input-request trust model.** `inputRequests` carry elicitation and sampling payloads from the server through the client to the user or model. Hosts **MUST** apply the same trust model to these payloads as they would to standard elicitation/sampling requests. A task is not a higher-trust channel. + +## Reference Implementation + +Implemented in [mcpkit](https://github.com/panyam/mcpkit/blob/02cfbe0d2cada8167b9043b9130804c8638b0aa5/core/task_v2.go) (see [usage example](https://github.com/panyam/mcpkit/tree/02cfbe0d2cada8167b9043b9130804c8638b0aa5/examples/tasks-v2)).