Drop the hand-written list_tools now that rmcp emits cache hints

`#[tool_handler]` generated `ttl_ms: None, cache_scope: None`, but both are
required on a paginated result at 2026-07-28, so a strict client rejected
tools/list before it could reach a tool call. The server worked around that by
hand-writing list_tools purely to set the two fields.

rust-sdk#1120 fixed the macro, released in rmcp 3.1.1: it now emits the fields
when the negotiated revision expects them and omits them otherwise. Both
lockfiles move to 3.1.2 and the override goes away, so the server is back to the
plain `#[tool_handler]` path the SDK documents.

Verified on the raw wire: after a 2026-07-28 handshake, tools/list carries
`ttlMs: 0` and `cacheScope: "public"` with no code setting them, and the smoke
test's strict client still validates both tools' structured content.
This commit is contained in:
olaservo 2026-08-09 17:52:24 -07:00
commit ce055ae1fe
4 changed files with 31 additions and 69 deletions

View file

@ -61,17 +61,6 @@ version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "async-trait"
version = "0.1.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.3",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -218,12 +207,12 @@ dependencies = [
[[package]]
name = "darling"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
checksum = "88490bf1b990d87eaaa7ac8aa887f629a08e7359765b4911faf63c3763347d23"
dependencies = [
"darling_core 0.23.0",
"darling_macro 0.23.0",
"darling_core 0.24.0",
"darling_macro 0.24.0",
]
[[package]]
@ -242,15 +231,15 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
checksum = "084e274f91c482280130e1e34e0b8d6e66776a060d7b6de7b84289ca778868c4"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.106",
"syn 3.0.3",
]
[[package]]
@ -266,13 +255,13 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
checksum = "68f5792fa0d41cd2325ce0ffa64f0a340eaebd4971a3a0c5e1ffd2cc488a355e"
dependencies = [
"darling_core 0.23.0",
"darling_core 0.24.0",
"quote",
"syn 2.0.106",
"syn 3.0.3",
]
[[package]]
@ -1484,7 +1473,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@ -1690,11 +1679,10 @@ dependencies = [
[[package]]
name = "rmcp"
version = "3.1.0"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad26b216c966e987e80e86daf784a455c039c43d98575ceed57b8faa259e5695"
checksum = "c8dddc5b1924b9a59fba420166160ca2c4663a4e01803e52eda33070f56d63c8"
dependencies = [
"async-trait",
"base64 0.23.0",
"chrono",
"futures",
@ -1715,15 +1703,15 @@ dependencies = [
[[package]]
name = "rmcp-macros"
version = "3.1.0"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41bc748630c2be2a71b614c2f40d27bc0df0060696d224e1692c72345b7e0b79"
checksum = "6898e24cd16342b59bfa8a53c2c04b9cf62fc8a2cfea57b9c038b09984bfc521"
dependencies = [
"darling 0.23.0",
"darling 0.24.0",
"proc-macro2",
"quote",
"serde_json",
"syn 2.0.106",
"syn 3.0.3",
]
[[package]]

View file

@ -47,17 +47,6 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "async-trait"
version = "0.1.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.3",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -161,9 +150,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "darling"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
checksum = "88490bf1b990d87eaaa7ac8aa887f629a08e7359765b4911faf63c3763347d23"
dependencies = [
"darling_core",
"darling_macro",
@ -171,26 +160,26 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
checksum = "084e274f91c482280130e1e34e0b8d6e66776a060d7b6de7b84289ca778868c4"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.104",
"syn 3.0.3",
]
[[package]]
name = "darling_macro"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
checksum = "68f5792fa0d41cd2325ce0ffa64f0a340eaebd4971a3a0c5e1ffd2cc488a355e"
dependencies = [
"darling_core",
"quote",
"syn 2.0.104",
"syn 3.0.3",
]
[[package]]
@ -1101,11 +1090,10 @@ dependencies = [
[[package]]
name = "rmcp"
version = "3.1.0"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad26b216c966e987e80e86daf784a455c039c43d98575ceed57b8faa259e5695"
checksum = "c8dddc5b1924b9a59fba420166160ca2c4663a4e01803e52eda33070f56d63c8"
dependencies = [
"async-trait",
"base64 0.23.0",
"chrono",
"futures",
@ -1124,15 +1112,15 @@ dependencies = [
[[package]]
name = "rmcp-macros"
version = "3.1.0"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41bc748630c2be2a71b614c2f40d27bc0df0060696d224e1692c72345b7e0b79"
checksum = "6898e24cd16342b59bfa8a53c2c04b9cf62fc8a2cfea57b9c038b09984bfc521"
dependencies = [
"darling",
"proc-macro2",
"quote",
"serde_json",
"syn 2.0.104",
"syn 3.0.3",
]
[[package]]

View file

@ -7,5 +7,3 @@ See the [Build an MCP server](https://modelcontextprotocol.io/docs/develop/build
Both tools declare an `output_schema` and return `structured_content`. `get_forecast` returns an object; `get_alerts` returns a top-level JSON array, which protocol revision `2026-07-28` is the first to allow — see [Structured Content](https://modelcontextprotocol.io/specification/draft/server/tools#structured-content) in the spec.
Note that an array-rooted schema requires a `2026-07-28` client: rmcp sends it as written on every connection rather than projecting it down, so an older client rejects the tool list.
`list_tools` is hand-written because `#[tool_handler]` omits the SEP-2549 `ttl_ms` and `cache_scope` fields, which are required on a paginated result at this revision.

View file

@ -292,18 +292,6 @@ impl ServerHandler for Weather {
info.capabilities = ServerCapabilities::builder().enable_tools().build();
info
}
// Hand-written because `#[tool_handler]` generates `ttl_ms: None,
// cache_scope: None`, and both are required at revision 2026-07-28.
async fn list_tools(
&self,
_request: Option<PaginatedRequestParams>,
_context: rmcp::service::RequestContext<rmcp::RoleServer>,
) -> Result<ListToolsResult, ErrorData> {
Ok(ListToolsResult::with_all_items(self.tool_router.list_all())
.with_ttl_ms(60_000)
.with_cache_scope(CacheScope::Public))
}
}
#[tokio::main]