fix: align task response types with MCP spec (#658)
This commit is contained in:
parent
453032faed
commit
08a5b0551b
6 changed files with 349 additions and 134 deletions
|
|
@ -47,7 +47,7 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
status: rmcp::model::TaskStatus::Working,
|
status: rmcp::model::TaskStatus::Working,
|
||||||
status_message: None,
|
status_message: None,
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
last_updated_at: Some(timestamp),
|
last_updated_at: timestamp,
|
||||||
ttl: None,
|
ttl: None,
|
||||||
poll_interval: None,
|
poll_interval: None,
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +111,7 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
status: rmcp::model::TaskStatus::Working,
|
status: rmcp::model::TaskStatus::Working,
|
||||||
status_message: Some("Task accepted".to_string()),
|
status_message: Some("Task accepted".to_string()),
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
last_updated_at: Some(timestamp),
|
last_updated_at: timestamp,
|
||||||
ttl: None,
|
ttl: None,
|
||||||
poll_interval: None,
|
poll_interval: None,
|
||||||
};
|
};
|
||||||
|
|
@ -128,7 +128,7 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
&self,
|
&self,
|
||||||
request: rmcp::model::GetTaskInfoParam,
|
request: rmcp::model::GetTaskInfoParam,
|
||||||
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
||||||
) -> Result<rmcp::model::GetTaskInfoResult, McpError> {
|
) -> Result<rmcp::model::GetTaskResult, McpError> {
|
||||||
use rmcp::task_manager::current_timestamp;
|
use rmcp::task_manager::current_timestamp;
|
||||||
let task_id = request.task_id.clone();
|
let task_id = request.task_id.clone();
|
||||||
let mut processor = (#processor).lock().await;
|
let mut processor = (#processor).lock().await;
|
||||||
|
|
@ -156,11 +156,11 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
status,
|
status,
|
||||||
status_message: None,
|
status_message: None,
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
last_updated_at: Some(timestamp),
|
last_updated_at: timestamp,
|
||||||
ttl: completed_result.descriptor.ttl,
|
ttl: completed_result.descriptor.ttl,
|
||||||
poll_interval: None,
|
poll_interval: None,
|
||||||
};
|
};
|
||||||
return Ok(rmcp::model::GetTaskInfoResult { task: Some(task) });
|
return Ok(rmcp::model::GetTaskResult { meta: None, task });
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not completed, check running
|
// If not completed, check running
|
||||||
|
|
@ -172,14 +172,14 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
status: rmcp::model::TaskStatus::Working,
|
status: rmcp::model::TaskStatus::Working,
|
||||||
status_message: None,
|
status_message: None,
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
last_updated_at: Some(timestamp),
|
last_updated_at: timestamp,
|
||||||
ttl: None,
|
ttl: None,
|
||||||
poll_interval: None,
|
poll_interval: None,
|
||||||
};
|
};
|
||||||
return Ok(rmcp::model::GetTaskInfoResult { task: Some(task) });
|
return Ok(rmcp::model::GetTaskResult { meta: None, task });
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(rmcp::model::GetTaskInfoResult { task: None })
|
Err(McpError::resource_not_found(format!("task not found: {}", task_id), None))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
item_impl.items.push(syn::parse2::<ImplItem>(get_info_fn)?);
|
item_impl.items.push(syn::parse2::<ImplItem>(get_info_fn)?);
|
||||||
|
|
@ -191,7 +191,7 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
&self,
|
&self,
|
||||||
request: rmcp::model::GetTaskResultParam,
|
request: rmcp::model::GetTaskResultParam,
|
||||||
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
||||||
) -> Result<rmcp::model::TaskResult, McpError> {
|
) -> Result<rmcp::model::GetTaskPayloadResult, McpError> {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
let task_id = request.task_id.clone();
|
let task_id = request.task_id.clone();
|
||||||
|
|
||||||
|
|
@ -207,11 +207,7 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
match &tool.result {
|
match &tool.result {
|
||||||
Ok(call_tool) => {
|
Ok(call_tool) => {
|
||||||
let value = ::serde_json::to_value(call_tool).unwrap_or(::serde_json::Value::Null);
|
let value = ::serde_json::to_value(call_tool).unwrap_or(::serde_json::Value::Null);
|
||||||
return Ok(rmcp::model::TaskResult {
|
return Ok(rmcp::model::GetTaskPayloadResult(value));
|
||||||
content_type: "application/json".to_string(),
|
|
||||||
value,
|
|
||||||
summary: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Err(err) => return Err(McpError::internal_error(
|
Err(err) => return Err(McpError::internal_error(
|
||||||
format!("task failed: {}", err),
|
format!("task failed: {}", err),
|
||||||
|
|
@ -251,12 +247,23 @@ pub fn task_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
&self,
|
&self,
|
||||||
request: rmcp::model::CancelTaskParam,
|
request: rmcp::model::CancelTaskParam,
|
||||||
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
|
||||||
) -> Result<(), McpError> {
|
) -> Result<rmcp::model::CancelTaskResult, McpError> {
|
||||||
|
use rmcp::task_manager::current_timestamp;
|
||||||
let task_id = request.task_id;
|
let task_id = request.task_id;
|
||||||
let mut processor = (#processor).lock().await;
|
let mut processor = (#processor).lock().await;
|
||||||
|
|
||||||
if processor.cancel_task(&task_id) {
|
if processor.cancel_task(&task_id) {
|
||||||
return Ok(());
|
let timestamp = current_timestamp();
|
||||||
|
let task = rmcp::model::Task {
|
||||||
|
task_id,
|
||||||
|
status: rmcp::model::TaskStatus::Cancelled,
|
||||||
|
status_message: None,
|
||||||
|
created_at: timestamp.clone(),
|
||||||
|
last_updated_at: timestamp,
|
||||||
|
ttl: None,
|
||||||
|
poll_interval: None,
|
||||||
|
};
|
||||||
|
return Ok(rmcp::model::CancelTaskResult { meta: None, task });
|
||||||
}
|
}
|
||||||
|
|
||||||
// If already completed, signal it's not cancellable
|
// If already completed, signal it's not cancellable
|
||||||
|
|
|
||||||
|
|
@ -116,15 +116,15 @@ impl<H: ServerHandler> Service<RoleServer> for H {
|
||||||
ClientRequest::GetTaskInfoRequest(request) => self
|
ClientRequest::GetTaskInfoRequest(request) => self
|
||||||
.get_task_info(request.params, context)
|
.get_task_info(request.params, context)
|
||||||
.await
|
.await
|
||||||
.map(ServerResult::GetTaskInfoResult),
|
.map(ServerResult::GetTaskResult),
|
||||||
ClientRequest::GetTaskResultRequest(request) => self
|
ClientRequest::GetTaskResultRequest(request) => self
|
||||||
.get_task_result(request.params, context)
|
.get_task_result(request.params, context)
|
||||||
.await
|
.await
|
||||||
.map(ServerResult::TaskResult),
|
.map(ServerResult::GetTaskPayloadResult),
|
||||||
ClientRequest::CancelTaskRequest(request) => self
|
ClientRequest::CancelTaskRequest(request) => self
|
||||||
.cancel_task(request.params, context)
|
.cancel_task(request.params, context)
|
||||||
.await
|
.await
|
||||||
.map(ServerResult::empty),
|
.map(ServerResult::CancelTaskResult),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,7 +339,8 @@ pub trait ServerHandler: Sized + Send + Sync + 'static {
|
||||||
&self,
|
&self,
|
||||||
request: GetTaskInfoParams,
|
request: GetTaskInfoParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<GetTaskInfoResult, McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<GetTaskResult, McpError>> + Send + '_ {
|
||||||
|
let _ = (request, context);
|
||||||
std::future::ready(Err(McpError::method_not_found::<GetTaskInfoMethod>()))
|
std::future::ready(Err(McpError::method_not_found::<GetTaskInfoMethod>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +348,7 @@ pub trait ServerHandler: Sized + Send + Sync + 'static {
|
||||||
&self,
|
&self,
|
||||||
request: GetTaskResultParams,
|
request: GetTaskResultParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<TaskResult, McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<GetTaskPayloadResult, McpError>> + Send + '_ {
|
||||||
let _ = (request, context);
|
let _ = (request, context);
|
||||||
std::future::ready(Err(McpError::method_not_found::<GetTaskResultMethod>()))
|
std::future::ready(Err(McpError::method_not_found::<GetTaskResultMethod>()))
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +357,7 @@ pub trait ServerHandler: Sized + Send + Sync + 'static {
|
||||||
&self,
|
&self,
|
||||||
request: CancelTaskParams,
|
request: CancelTaskParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<CancelTaskResult, McpError>> + Send + '_ {
|
||||||
let _ = (request, context);
|
let _ = (request, context);
|
||||||
std::future::ready(Err(McpError::method_not_found::<CancelTaskMethod>()))
|
std::future::ready(Err(McpError::method_not_found::<CancelTaskMethod>()))
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +544,7 @@ macro_rules! impl_server_handler_for_wrapper {
|
||||||
&self,
|
&self,
|
||||||
request: GetTaskInfoParams,
|
request: GetTaskInfoParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<GetTaskInfoResult, McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<GetTaskResult, McpError>> + Send + '_ {
|
||||||
(**self).get_task_info(request, context)
|
(**self).get_task_info(request, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,7 +552,7 @@ macro_rules! impl_server_handler_for_wrapper {
|
||||||
&self,
|
&self,
|
||||||
request: GetTaskResultParams,
|
request: GetTaskResultParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<TaskResult, McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<GetTaskPayloadResult, McpError>> + Send + '_ {
|
||||||
(**self).get_task_result(request, context)
|
(**self).get_task_result(request, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -559,7 +560,7 @@ macro_rules! impl_server_handler_for_wrapper {
|
||||||
&self,
|
&self,
|
||||||
request: CancelTaskParams,
|
request: CancelTaskParams,
|
||||||
context: RequestContext<RoleServer>,
|
context: RequestContext<RoleServer>,
|
||||||
) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
|
) -> impl Future<Output = Result<CancelTaskResult, McpError>> + Send + '_ {
|
||||||
(**self).cancel_task(request, context)
|
(**self).cancel_task(request, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2537,14 +2537,9 @@ impl RequestParamsMeta for CancelTaskParams {
|
||||||
/// Deprecated: Use [`CancelTaskParams`] instead (SEP-1319 compliance).
|
/// Deprecated: Use [`CancelTaskParams`] instead (SEP-1319 compliance).
|
||||||
#[deprecated(since = "0.13.0", note = "Use CancelTaskParams instead")]
|
#[deprecated(since = "0.13.0", note = "Use CancelTaskParams instead")]
|
||||||
pub type CancelTaskParam = CancelTaskParams;
|
pub type CancelTaskParam = CancelTaskParams;
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
/// Deprecated: Use [`GetTaskResult`] instead (spec alignment).
|
||||||
#[serde(rename_all = "camelCase")]
|
#[deprecated(since = "0.15.0", note = "Use GetTaskResult instead")]
|
||||||
#[serde(deny_unknown_fields)]
|
pub type GetTaskInfoResult = GetTaskResult;
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
|
||||||
pub struct GetTaskInfoResult {
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub task: Option<crate::model::Task>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
@ -2720,9 +2715,10 @@ ts_union!(
|
||||||
| EmptyResult
|
| EmptyResult
|
||||||
| CreateTaskResult
|
| CreateTaskResult
|
||||||
| ListTasksResult
|
| ListTasksResult
|
||||||
| GetTaskInfoResult
|
| GetTaskResult
|
||||||
| TaskResult
|
| CancelTaskResult
|
||||||
| CustomResult
|
| CustomResult
|
||||||
|
| GetTaskPayloadResult
|
||||||
;
|
;
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use super::Meta;
|
||||||
|
|
||||||
/// Canonical task lifecycle status as defined by SEP-1686.
|
/// Canonical task lifecycle status as defined by SEP-1686.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
|
@ -19,21 +21,10 @@ pub enum TaskStatus {
|
||||||
Cancelled,
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Final result for a succeeded task (returned from `tasks/result`).
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
|
||||||
pub struct TaskResult {
|
|
||||||
/// MIME type or custom content-type identifier.
|
|
||||||
pub content_type: String,
|
|
||||||
/// The actual result payload, matching the underlying request's schema.
|
|
||||||
pub value: Value,
|
|
||||||
/// Optional short summary for UI surfaces.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub summary: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Primary Task object that surfaces metadata during the task lifecycle.
|
/// Primary Task object that surfaces metadata during the task lifecycle.
|
||||||
|
///
|
||||||
|
/// Per spec, `lastUpdatedAt` and `ttl` are required fields.
|
||||||
|
/// `ttl` is nullable (`null` means unlimited retention).
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
|
@ -48,10 +39,9 @@ pub struct Task {
|
||||||
/// ISO-8601 creation timestamp.
|
/// ISO-8601 creation timestamp.
|
||||||
pub created_at: String,
|
pub created_at: String,
|
||||||
/// ISO-8601 timestamp for the most recent status change.
|
/// ISO-8601 timestamp for the most recent status change.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
pub last_updated_at: String,
|
||||||
pub last_updated_at: Option<String>,
|
|
||||||
/// Retention window in milliseconds that the receiver agreed to honor.
|
/// Retention window in milliseconds that the receiver agreed to honor.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
/// `None` (serialized as `null`) means unlimited retention.
|
||||||
pub ttl: Option<u64>,
|
pub ttl: Option<u64>,
|
||||||
/// Suggested polling interval (milliseconds).
|
/// Suggested polling interval (milliseconds).
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
@ -66,6 +56,43 @@ pub struct CreateTaskResult {
|
||||||
pub task: Task,
|
pub task: Task,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Response to a `tasks/get` request.
|
||||||
|
///
|
||||||
|
/// Per spec, `GetTaskResult = allOf[Result, Task]` — the Task fields are
|
||||||
|
/// flattened at the top level, not nested under a `task` key.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
pub struct GetTaskResult {
|
||||||
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub meta: Option<Meta>,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub task: Task,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Response to a `tasks/result` request.
|
||||||
|
///
|
||||||
|
/// Per spec, the result structure matches the original request type
|
||||||
|
/// (e.g., `CallToolResult` for `tools/call`). This is represented as
|
||||||
|
/// an open object. The payload is the original request's result
|
||||||
|
/// serialized as a JSON value.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
pub struct GetTaskPayloadResult(pub Value);
|
||||||
|
|
||||||
|
/// Response to a `tasks/cancel` request.
|
||||||
|
///
|
||||||
|
/// Per spec, `CancelTaskResult = allOf[Result, Task]` — same shape as `GetTaskResult`.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
pub struct CancelTaskResult {
|
||||||
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub meta: Option<Meta>,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub task: Task,
|
||||||
|
}
|
||||||
|
|
||||||
/// Paginated list of tasks
|
/// Paginated list of tasks
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,70 @@
|
||||||
"content"
|
"content"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"CancelTaskResult": {
|
||||||
|
"description": "Response to a `tasks/cancel` request.\n\nPer spec, `CancelTaskResult = allOf[Result, Task]` — same shape as `GetTaskResult`.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"_meta": {
|
||||||
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"description": "ISO-8601 creation timestamp.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastUpdatedAt": {
|
||||||
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pollInterval": {
|
||||||
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "Current lifecycle status (see [`TaskStatus`]).",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/TaskStatus"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"statusMessage": {
|
||||||
|
"description": "Optional human-readable status message for UI surfaces.",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"taskId": {
|
||||||
|
"description": "Unique task identifier generated by the receiver.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"taskId",
|
||||||
|
"status",
|
||||||
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
|
]
|
||||||
|
},
|
||||||
"CancelledNotificationMethod": {
|
"CancelledNotificationMethod": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "const",
|
"format": "const",
|
||||||
|
|
@ -937,21 +1001,72 @@
|
||||||
"messages"
|
"messages"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"GetTaskInfoResult": {
|
"GetTaskPayloadResult": {
|
||||||
|
"description": "Response to a `tasks/result` request.\n\nPer spec, the result structure matches the original request type\n(e.g., `CallToolResult` for `tools/call`). This is represented as\nan open object. The payload is the original request's result\nserialized as a JSON value."
|
||||||
|
},
|
||||||
|
"GetTaskResult": {
|
||||||
|
"description": "Response to a `tasks/get` request.\n\nPer spec, `GetTaskResult = allOf[Result, Task]` — the Task fields are\nflattened at the top level, not nested under a `task` key.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"task": {
|
"_meta": {
|
||||||
"anyOf": [
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"description": "ISO-8601 creation timestamp.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastUpdatedAt": {
|
||||||
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pollInterval": {
|
||||||
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "Current lifecycle status (see [`TaskStatus`]).",
|
||||||
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Task"
|
"$ref": "#/definitions/TaskStatus"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"statusMessage": {
|
||||||
|
"description": "Optional human-readable status message for UI surfaces.",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"taskId": {
|
||||||
|
"description": "Unique task identifier generated by the receiver.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"required": [
|
||||||
|
"taskId",
|
||||||
|
"status",
|
||||||
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"Icon": {
|
"Icon": {
|
||||||
"description": "A URL pointing to an icon resource or a base64-encoded data URI.\n\nClients that support rendering icons MUST support at least the following MIME types:\n- image/png - PNG images (safe, universal compatibility)\n- image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)\n\nClients that support rendering icons SHOULD also support:\n- image/svg+xml - SVG images (scalable but requires security precautions)\n- image/webp - WebP images (modern, efficient format)",
|
"description": "A URL pointing to an icon resource or a base64-encoded data URI.\n\nClients that support rendering icons MUST support at least the following MIME types:\n- image/png - PNG images (safe, universal compatibility)\n- image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)\n\nClients that support rendering icons SHOULD also support:\n- image/svg+xml - SVG images (scalable but requires security precautions)\n- image/webp - WebP images (modern, efficient format)",
|
||||||
|
|
@ -2701,13 +2816,16 @@
|
||||||
"$ref": "#/definitions/ListTasksResult"
|
"$ref": "#/definitions/ListTasksResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/GetTaskInfoResult"
|
"$ref": "#/definitions/GetTaskResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/TaskResult"
|
"$ref": "#/definitions/CancelTaskResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/CustomResult"
|
"$ref": "#/definitions/CustomResult"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/GetTaskPayloadResult"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -2813,7 +2931,7 @@
|
||||||
"const": "string"
|
"const": "string"
|
||||||
},
|
},
|
||||||
"Task": {
|
"Task": {
|
||||||
"description": "Primary Task object that surfaces metadata during the task lifecycle.",
|
"description": "Primary Task object that surfaces metadata during the task lifecycle.\n\nPer spec, `lastUpdatedAt` and `ttl` are required fields.\n`ttl` is nullable (`null` means unlimited retention).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
|
|
@ -2822,10 +2940,7 @@
|
||||||
},
|
},
|
||||||
"lastUpdatedAt": {
|
"lastUpdatedAt": {
|
||||||
"description": "ISO-8601 timestamp for the most recent status change.",
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
"type": [
|
"type": "string"
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"pollInterval": {
|
"pollInterval": {
|
||||||
"description": "Suggested polling interval (milliseconds).",
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
|
@ -2856,7 +2971,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ttl": {
|
"ttl": {
|
||||||
"description": "Retention window in milliseconds that the receiver agreed to honor.",
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
"type": [
|
"type": [
|
||||||
"integer",
|
"integer",
|
||||||
"null"
|
"null"
|
||||||
|
|
@ -2868,7 +2983,8 @@
|
||||||
"required": [
|
"required": [
|
||||||
"taskId",
|
"taskId",
|
||||||
"status",
|
"status",
|
||||||
"createdAt"
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"TaskRequestsCapability": {
|
"TaskRequestsCapability": {
|
||||||
|
|
@ -2907,30 +3023,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TaskResult": {
|
|
||||||
"description": "Final result for a succeeded task (returned from `tasks/result`).",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"contentType": {
|
|
||||||
"description": "MIME type or custom content-type identifier.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"summary": {
|
|
||||||
"description": "Optional short summary for UI surfaces.",
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"description": "The actual result payload, matching the underlying request's schema."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"contentType",
|
|
||||||
"value"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"TaskStatus": {
|
"TaskStatus": {
|
||||||
"description": "Canonical task lifecycle status as defined by SEP-1686.",
|
"description": "Canonical task lifecycle status as defined by SEP-1686.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,70 @@
|
||||||
"content"
|
"content"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"CancelTaskResult": {
|
||||||
|
"description": "Response to a `tasks/cancel` request.\n\nPer spec, `CancelTaskResult = allOf[Result, Task]` — same shape as `GetTaskResult`.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"_meta": {
|
||||||
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"description": "ISO-8601 creation timestamp.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastUpdatedAt": {
|
||||||
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pollInterval": {
|
||||||
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "Current lifecycle status (see [`TaskStatus`]).",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/TaskStatus"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"statusMessage": {
|
||||||
|
"description": "Optional human-readable status message for UI surfaces.",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"taskId": {
|
||||||
|
"description": "Unique task identifier generated by the receiver.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"taskId",
|
||||||
|
"status",
|
||||||
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
|
]
|
||||||
|
},
|
||||||
"CancelledNotificationMethod": {
|
"CancelledNotificationMethod": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "const",
|
"format": "const",
|
||||||
|
|
@ -937,21 +1001,72 @@
|
||||||
"messages"
|
"messages"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"GetTaskInfoResult": {
|
"GetTaskPayloadResult": {
|
||||||
|
"description": "Response to a `tasks/result` request.\n\nPer spec, the result structure matches the original request type\n(e.g., `CallToolResult` for `tools/call`). This is represented as\nan open object. The payload is the original request's result\nserialized as a JSON value."
|
||||||
|
},
|
||||||
|
"GetTaskResult": {
|
||||||
|
"description": "Response to a `tasks/get` request.\n\nPer spec, `GetTaskResult = allOf[Result, Task]` — the Task fields are\nflattened at the top level, not nested under a `task` key.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"task": {
|
"_meta": {
|
||||||
"anyOf": [
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"description": "ISO-8601 creation timestamp.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastUpdatedAt": {
|
||||||
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pollInterval": {
|
||||||
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "Current lifecycle status (see [`TaskStatus`]).",
|
||||||
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Task"
|
"$ref": "#/definitions/TaskStatus"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"statusMessage": {
|
||||||
|
"description": "Optional human-readable status message for UI surfaces.",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"taskId": {
|
||||||
|
"description": "Unique task identifier generated by the receiver.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"required": [
|
||||||
|
"taskId",
|
||||||
|
"status",
|
||||||
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"Icon": {
|
"Icon": {
|
||||||
"description": "A URL pointing to an icon resource or a base64-encoded data URI.\n\nClients that support rendering icons MUST support at least the following MIME types:\n- image/png - PNG images (safe, universal compatibility)\n- image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)\n\nClients that support rendering icons SHOULD also support:\n- image/svg+xml - SVG images (scalable but requires security precautions)\n- image/webp - WebP images (modern, efficient format)",
|
"description": "A URL pointing to an icon resource or a base64-encoded data URI.\n\nClients that support rendering icons MUST support at least the following MIME types:\n- image/png - PNG images (safe, universal compatibility)\n- image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)\n\nClients that support rendering icons SHOULD also support:\n- image/svg+xml - SVG images (scalable but requires security precautions)\n- image/webp - WebP images (modern, efficient format)",
|
||||||
|
|
@ -2701,13 +2816,16 @@
|
||||||
"$ref": "#/definitions/ListTasksResult"
|
"$ref": "#/definitions/ListTasksResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/GetTaskInfoResult"
|
"$ref": "#/definitions/GetTaskResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/TaskResult"
|
"$ref": "#/definitions/CancelTaskResult"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/CustomResult"
|
"$ref": "#/definitions/CustomResult"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/GetTaskPayloadResult"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -2813,7 +2931,7 @@
|
||||||
"const": "string"
|
"const": "string"
|
||||||
},
|
},
|
||||||
"Task": {
|
"Task": {
|
||||||
"description": "Primary Task object that surfaces metadata during the task lifecycle.",
|
"description": "Primary Task object that surfaces metadata during the task lifecycle.\n\nPer spec, `lastUpdatedAt` and `ttl` are required fields.\n`ttl` is nullable (`null` means unlimited retention).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
|
|
@ -2822,10 +2940,7 @@
|
||||||
},
|
},
|
||||||
"lastUpdatedAt": {
|
"lastUpdatedAt": {
|
||||||
"description": "ISO-8601 timestamp for the most recent status change.",
|
"description": "ISO-8601 timestamp for the most recent status change.",
|
||||||
"type": [
|
"type": "string"
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"pollInterval": {
|
"pollInterval": {
|
||||||
"description": "Suggested polling interval (milliseconds).",
|
"description": "Suggested polling interval (milliseconds).",
|
||||||
|
|
@ -2856,7 +2971,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ttl": {
|
"ttl": {
|
||||||
"description": "Retention window in milliseconds that the receiver agreed to honor.",
|
"description": "Retention window in milliseconds that the receiver agreed to honor.\n`None` (serialized as `null`) means unlimited retention.",
|
||||||
"type": [
|
"type": [
|
||||||
"integer",
|
"integer",
|
||||||
"null"
|
"null"
|
||||||
|
|
@ -2868,7 +2983,8 @@
|
||||||
"required": [
|
"required": [
|
||||||
"taskId",
|
"taskId",
|
||||||
"status",
|
"status",
|
||||||
"createdAt"
|
"createdAt",
|
||||||
|
"lastUpdatedAt"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"TaskRequestsCapability": {
|
"TaskRequestsCapability": {
|
||||||
|
|
@ -2907,30 +3023,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TaskResult": {
|
|
||||||
"description": "Final result for a succeeded task (returned from `tasks/result`).",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"contentType": {
|
|
||||||
"description": "MIME type or custom content-type identifier.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"summary": {
|
|
||||||
"description": "Optional short summary for UI surfaces.",
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"description": "The actual result payload, matching the underlying request's schema."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"contentType",
|
|
||||||
"value"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"TaskStatus": {
|
"TaskStatus": {
|
||||||
"description": "Canonical task lifecycle status as defined by SEP-1686.",
|
"description": "Canonical task lifecycle status as defined by SEP-1686.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue