feat!: implement SEP-2549 cache hints (#889)
implements https://github.com/modelcontextprotocol/rust-sdk/issues/875 Co-authored-by: Jack Amadeo <jackamadeo@squareup.com>
This commit is contained in:
parent
2d4c29fb02
commit
d8331d9442
6 changed files with 403 additions and 7 deletions
|
|
@ -65,6 +65,8 @@ pub fn prompt_handler(attr: TokenStream, input: TokenStream) -> syn::Result<Toke
|
||||||
prompts,
|
prompts,
|
||||||
meta: #meta,
|
meta: #meta,
|
||||||
next_cursor: None,
|
next_cursor: None,
|
||||||
|
ttl_ms: None,
|
||||||
|
cache_scope: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@ pub fn tool_handler(attr: TokenStream, input: TokenStream) -> syn::Result<TokenS
|
||||||
tools: #router.list_all(),
|
tools: #router.list_all(),
|
||||||
meta: #result_meta,
|
meta: #result_meta,
|
||||||
next_cursor: None,
|
next_cursor: None,
|
||||||
|
ttl_ms: None,
|
||||||
|
cache_scope: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
|
||||||
|
|
@ -1246,6 +1246,34 @@ pub type ProgressNotification = Notification<ProgressNotificationMethod, Progres
|
||||||
|
|
||||||
pub type Cursor = String;
|
pub type Cursor = String;
|
||||||
|
|
||||||
|
/// Scope describing who may cache cacheable list/read results (SEP-2549).
|
||||||
|
///
|
||||||
|
/// Defaults to [`CacheScope::Public`] when absent from the wire.
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum CacheScope {
|
||||||
|
/// Any client or intermediary may cache and serve the response to any user.
|
||||||
|
#[default]
|
||||||
|
Public,
|
||||||
|
/// Only the requesting user's client may cache the response.
|
||||||
|
Private,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Normalize a `ttlMs` value during deserialization.
|
||||||
|
///
|
||||||
|
/// Per SEP-2549, `ttlMs` MUST be `>= 0`; if a server returns a negative value,
|
||||||
|
/// clients SHOULD treat it as `0` (immediately stale). This tolerates that case
|
||||||
|
/// rather than erroring, while still accepting an absent field as `None`.
|
||||||
|
fn deserialize_ttl_ms<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let value = Option::<i64>::deserialize(deserializer)?;
|
||||||
|
Ok(value.map(|ttl_ms| ttl_ms.max(0) as u64))
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! paginated_result {
|
macro_rules! paginated_result {
|
||||||
($t:ident {
|
($t:ident {
|
||||||
$i_item: ident: $t_item: ty
|
$i_item: ident: $t_item: ty
|
||||||
|
|
@ -1258,24 +1286,50 @@ macro_rules! paginated_result {
|
||||||
/// Result type discriminator. Absent values deserialize as `"complete"`.
|
/// Result type discriminator. Absent values deserialize as `"complete"`.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub result_type: ResultType,
|
pub result_type: ResultType,
|
||||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
pub meta: Option<Meta>,
|
pub meta: Option<Meta>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub next_cursor: Option<Cursor>,
|
pub next_cursor: Option<Cursor>,
|
||||||
|
/// Time, in milliseconds, that this result may be treated as fresh (SEP-2549).
|
||||||
|
/// Required by spec version 2026-07-28, but optional here to maintain compatibility
|
||||||
|
/// with older spec versions.
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_ttl_ms",
|
||||||
|
skip_serializing_if = "Option::is_none"
|
||||||
|
)]
|
||||||
|
pub ttl_ms: Option<u64>,
|
||||||
|
/// Scope describing who may cache this result (SEP-2549).
|
||||||
|
/// Required by spec version 2026-07-28, but optional here to maintain compatibility
|
||||||
|
/// with older spec versions.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub cache_scope: Option<CacheScope>,
|
||||||
pub $i_item: $t_item,
|
pub $i_item: $t_item,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $t {
|
impl $t {
|
||||||
pub fn with_all_items(
|
pub fn with_all_items(items: $t_item) -> Self {
|
||||||
items: $t_item,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
result_type: ResultType::default(),
|
result_type: ResultType::default(),
|
||||||
meta: None,
|
meta: None,
|
||||||
next_cursor: None,
|
next_cursor: None,
|
||||||
|
ttl_ms: None,
|
||||||
|
cache_scope: None,
|
||||||
$i_item: items,
|
$i_item: items,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the time, in milliseconds, that this result may be treated as fresh.
|
||||||
|
pub fn with_ttl_ms(mut self, ttl_ms: u64) -> Self {
|
||||||
|
self.ttl_ms = Some(ttl_ms);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the cache scope for this result.
|
||||||
|
pub fn with_cache_scope(mut self, cache_scope: CacheScope) -> Self {
|
||||||
|
self.cache_scope = Some(cache_scope);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1368,12 +1422,27 @@ pub type ReadResourceRequestParam = ReadResourceRequestParams;
|
||||||
|
|
||||||
/// Result containing the contents of a read resource
|
/// Result containing the contents of a read resource
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct ReadResourceResult {
|
pub struct ReadResourceResult {
|
||||||
/// Result type discriminator. Absent values deserialize as `"complete"`.
|
/// Result type discriminator. Absent values deserialize as `"complete"`.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub result_type: ResultType,
|
pub result_type: ResultType,
|
||||||
|
/// Time, in milliseconds, that this result may be treated as fresh (SEP-2549).
|
||||||
|
/// Required by spec version 2026-07-28, but optional here to maintain compatibility
|
||||||
|
/// with older spec versions.
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_ttl_ms",
|
||||||
|
skip_serializing_if = "Option::is_none"
|
||||||
|
)]
|
||||||
|
pub ttl_ms: Option<u64>,
|
||||||
|
/// Scope describing who may cache this result (SEP-2549).
|
||||||
|
/// Required by spec version 2026-07-28, but optional here to maintain compatibility
|
||||||
|
/// with older spec versions.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub cache_scope: Option<CacheScope>,
|
||||||
/// The actual content of the resource
|
/// The actual content of the resource
|
||||||
pub contents: Vec<ResourceContents>,
|
pub contents: Vec<ResourceContents>,
|
||||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||||
|
|
@ -1385,10 +1454,24 @@ impl ReadResourceResult {
|
||||||
pub fn new(contents: Vec<ResourceContents>) -> Self {
|
pub fn new(contents: Vec<ResourceContents>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
result_type: ResultType::default(),
|
result_type: ResultType::default(),
|
||||||
|
ttl_ms: None,
|
||||||
|
cache_scope: None,
|
||||||
contents,
|
contents,
|
||||||
meta: None,
|
meta: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the time, in milliseconds, that this result may be treated as fresh.
|
||||||
|
pub fn with_ttl_ms(mut self, ttl_ms: u64) -> Self {
|
||||||
|
self.ttl_ms = Some(ttl_ms);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the cache scope for this result.
|
||||||
|
pub fn with_cache_scope(mut self, cache_scope: CacheScope) -> Self {
|
||||||
|
self.cache_scope = Some(cache_scope);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request to read a specific resource
|
/// Request to read a specific resource
|
||||||
|
|
|
||||||
79
crates/rmcp/tests/test_cache_hints.rs
Normal file
79
crates/rmcp/tests/test_cache_hints.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
use rmcp::model::{CacheScope, ListToolsResult, ReadResourceResult, ResourceContents};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn paginated_results_serialize_cache_hints_as_top_level_fields() {
|
||||||
|
let result = ListToolsResult::with_all_items(Vec::new())
|
||||||
|
.with_ttl_ms(5_000)
|
||||||
|
.with_cache_scope(CacheScope::Private);
|
||||||
|
|
||||||
|
let actual = serde_json::to_value(result).expect("serialize list tools result");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
actual,
|
||||||
|
json!({
|
||||||
|
"ttlMs": 5000,
|
||||||
|
"cacheScope": "private",
|
||||||
|
"tools": [],
|
||||||
|
"resultType": "complete"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert!(actual.get("_meta").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read_resource_results_serialize_cache_hints_as_top_level_fields() {
|
||||||
|
let result =
|
||||||
|
ReadResourceResult::new(vec![ResourceContents::text("hello", "file:///example.txt")])
|
||||||
|
.with_ttl_ms(10_000)
|
||||||
|
.with_cache_scope(CacheScope::Public);
|
||||||
|
|
||||||
|
let actual = serde_json::to_value(result).expect("serialize read resource result");
|
||||||
|
|
||||||
|
assert_eq!(actual["ttlMs"], 10000);
|
||||||
|
assert_eq!(actual["cacheScope"], "public");
|
||||||
|
assert!(actual["contents"][0].get("_meta").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cache_hints_are_omitted_when_absent() {
|
||||||
|
let result = ListToolsResult::with_all_items(Vec::new());
|
||||||
|
let actual = serde_json::to_value(result).expect("serialize list tools result");
|
||||||
|
|
||||||
|
assert_eq!(actual, json!({ "tools": [], "resultType": "complete" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cache_hints_default_to_none_and_negative_ttl_is_normalized_to_zero() {
|
||||||
|
let absent: ListToolsResult = serde_json::from_value(json!({
|
||||||
|
"tools": []
|
||||||
|
}))
|
||||||
|
.expect("deserialize result without ttlMs");
|
||||||
|
assert_eq!(absent.ttl_ms, None);
|
||||||
|
assert_eq!(absent.cache_scope, None);
|
||||||
|
|
||||||
|
let negative: ReadResourceResult = serde_json::from_value(json!({
|
||||||
|
"ttlMs": -42,
|
||||||
|
"cacheScope": "private",
|
||||||
|
"contents": []
|
||||||
|
}))
|
||||||
|
.expect("deserialize result with negative ttlMs");
|
||||||
|
assert_eq!(negative.ttl_ms, Some(0));
|
||||||
|
assert_eq!(negative.cache_scope, Some(CacheScope::Private));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cache_scope_round_trips() {
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(CacheScope::Public).unwrap(),
|
||||||
|
json!("public")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(CacheScope::Private).unwrap(),
|
||||||
|
json!("private")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::from_value::<CacheScope>(json!("private")).unwrap(),
|
||||||
|
CacheScope::Private
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -150,6 +150,21 @@
|
||||||
"format": "const",
|
"format": "const",
|
||||||
"const": "boolean"
|
"const": "boolean"
|
||||||
},
|
},
|
||||||
|
"CacheScope": {
|
||||||
|
"description": "Scope describing who may cache cacheable list/read results (SEP-2549).\n\nDefaults to [`CacheScope::Public`] when absent from the wire.",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"description": "Any client or intermediary may cache and serve the response to any user.",
|
||||||
|
"type": "string",
|
||||||
|
"const": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Only the requesting user's client may cache the response.",
|
||||||
|
"type": "string",
|
||||||
|
"const": "private"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"CallToolResult": {
|
"CallToolResult": {
|
||||||
"description": "The result of a tool call operation.\n\nContains the content returned by the tool execution and an optional\nflag indicating whether the operation resulted in an error.",
|
"description": "The result of a tool call operation.\n\nContains the content returned by the tool execution and an optional\nflag indicating whether the operation resulted in an error.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -1515,6 +1530,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1535,6 +1561,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1551,6 +1586,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1571,6 +1617,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1587,6 +1642,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1607,6 +1673,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1655,6 +1730,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1675,6 +1761,15 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Tool"
|
"$ref": "#/definitions/Tool"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -2214,6 +2309,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"contents": {
|
"contents": {
|
||||||
"description": "The actual content of the resource",
|
"description": "The actual content of the resource",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|
@ -2221,7 +2327,7 @@
|
||||||
"$ref": "#/definitions/ResourceContents"
|
"$ref": "#/definitions/ResourceContents"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"result_type": {
|
"resultType": {
|
||||||
"description": "Result type discriminator. Absent values deserialize as `\"complete\"`.",
|
"description": "Result type discriminator. Absent values deserialize as `\"complete\"`.",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
|
|
@ -2229,6 +2335,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,21 @@
|
||||||
"format": "const",
|
"format": "const",
|
||||||
"const": "boolean"
|
"const": "boolean"
|
||||||
},
|
},
|
||||||
|
"CacheScope": {
|
||||||
|
"description": "Scope describing who may cache cacheable list/read results (SEP-2549).\n\nDefaults to [`CacheScope::Public`] when absent from the wire.",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"description": "Any client or intermediary may cache and serve the response to any user.",
|
||||||
|
"type": "string",
|
||||||
|
"const": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Only the requesting user's client may cache the response.",
|
||||||
|
"type": "string",
|
||||||
|
"const": "private"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"CallToolResult": {
|
"CallToolResult": {
|
||||||
"description": "The result of a tool call operation.\n\nContains the content returned by the tool execution and an optional\nflag indicating whether the operation resulted in an error.",
|
"description": "The result of a tool call operation.\n\nContains the content returned by the tool execution and an optional\nflag indicating whether the operation resulted in an error.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -1515,6 +1530,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1535,6 +1561,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1551,6 +1586,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1571,6 +1617,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1587,6 +1642,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1607,6 +1673,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1655,6 +1730,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"nextCursor": {
|
"nextCursor": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
|
|
@ -1675,6 +1761,15 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Tool"
|
"$ref": "#/definitions/Tool"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -2214,6 +2309,17 @@
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"cacheScope": {
|
||||||
|
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/CacheScope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"contents": {
|
"contents": {
|
||||||
"description": "The actual content of the resource",
|
"description": "The actual content of the resource",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|
@ -2221,7 +2327,7 @@
|
||||||
"$ref": "#/definitions/ResourceContents"
|
"$ref": "#/definitions/ResourceContents"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"result_type": {
|
"resultType": {
|
||||||
"description": "Result type discriminator. Absent values deserialize as `\"complete\"`.",
|
"description": "Result type discriminator. Absent values deserialize as `\"complete\"`.",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
|
|
@ -2229,6 +2335,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "complete"
|
"default": "complete"
|
||||||
|
},
|
||||||
|
"ttlMs": {
|
||||||
|
"description": "Time, in milliseconds, that this result may be treated as fresh (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue