diff --git a/Cargo.lock b/Cargo.lock index 2e53e3de..5c6183e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ dependencies = [ "metrics-exporter-prometheus", "notify", "pam-sys", - "rand 0.8.5", + "rand 0.8.8", "reqwest", "sea-orm", "sea-orm-migration", @@ -96,7 +96,7 @@ dependencies = [ "orchestrator", "reqwest", "rmcp", - "schemars 0.8.22", + "schemars 1.2.1", "serde", "serde_json", "tokio", @@ -128,17 +128,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.17", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.12" @@ -271,7 +260,7 @@ checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", - "cpufeatures", + "cpufeatures 0.2.17", "password-hash", ] @@ -328,7 +317,7 @@ version = "57.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8955af33b25f3b175ee10af580577280b4bd01f7e823d94c7cdef7cf8c9aef" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow-buffer", "arrow-data", "arrow-schema", @@ -366,7 +355,7 @@ dependencies = [ "arrow-schema", "arrow-select", "atoi", - "base64 0.22.1", + "base64", "chrono", "comfy-table", "half", @@ -486,7 +475,7 @@ version = "57.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68bf3e3efbd1278f770d67e5dc410257300b161b93baedb3aae836144edcaf4b" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow-array", "arrow-buffer", "arrow-data", @@ -665,7 +654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ "axum-core", - "base64 0.22.1", + "base64", "bytes", "form_urlencoded", "futures-util", @@ -713,12 +702,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -801,7 +784,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -819,7 +802,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" dependencies = [ - "base64 0.22.1", + "base64", "bollard-stubs", "bytes", "futures-core", @@ -933,28 +916,6 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytemuck" version = "1.25.0" @@ -1024,6 +985,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.44" @@ -1314,6 +1286,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -1370,9 +1351,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" dependencies = [ "crossbeam-utils", ] @@ -1657,7 +1638,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "205dc1e20441973f470e6b7ef87626a3b9187970e5106058fef1b713047f770c" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "arrow-ipc", "chrono", @@ -1852,7 +1833,7 @@ checksum = "49b82962015cc3db4d7662459c9f7fcda0591b5edacb8af1cf3bc3031f274800" dependencies = [ "arrow", "arrow-buffer", - "base64 0.22.1", + "base64", "blake2", "blake3", "chrono", @@ -1881,7 +1862,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e42c227d9e55a6c8041785d4a8a117e4de531033d480aae10984247ac62e27e" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "datafusion-common", "datafusion-doc", @@ -1902,7 +1883,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cead3cfed825b0b688700f4338d281cd7857e4907775a5b9554c083edd5f3f95" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "datafusion-common", "datafusion-expr-common", @@ -2012,7 +1993,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "987c5e29e96186589301b42e25aa7d11bbe319a73eb02ef8d755edc55b5b89fc" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "datafusion-common", "datafusion-expr", @@ -2050,7 +2031,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "602d1970c0fe87f1c3a36665d131fbfe1c4379d35f8fc5ec43a362229ad2954d" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "chrono", "datafusion-common", @@ -2085,7 +2066,7 @@ version = "52.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c21d94141ea5043e98793f170798e9c1887095813b8291c5260599341e383a38" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "arrow-ord", "arrow-schema", @@ -2455,9 +2436,9 @@ dependencies = [ [[package]] name = "ethnum" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" +checksum = "40404c3f5f511ec4da6fe866ddf6a717c309fdbb69fbbad7b0f3edab8f2e835f" [[package]] name = "event-listener" @@ -2758,11 +2739,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -2772,10 +2751,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", + "wasm-bindgen", ] [[package]] @@ -2786,9 +2768,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.4.13" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", @@ -2820,9 +2802,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] [[package]] name = "hashbrown" @@ -3059,7 +3038,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-channel", "futures-util", @@ -3957,7 +3936,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b79dd30fddeb0f21d090c502f937aa4862b5a352e74c47e35c6c76fec9f31534" dependencies = [ - "ahash 0.8.12", + "ahash", "arrow", "arrow-array", "arrow-cast", @@ -4336,7 +4315,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" dependencies = [ - "ahash 0.8.12", + "ahash", "portable-atomic", ] @@ -4346,7 +4325,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" dependencies = [ - "base64 0.22.1", + "base64", "indexmap 2.13.0", "metrics", "metrics-util", @@ -4614,7 +4593,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.8", "smallvec", "zeroize", ] @@ -4884,6 +4863,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "path_abs" version = "0.5.1" @@ -5209,26 +5194,6 @@ dependencies = [ "prost", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "quanta" version = "0.12.6" @@ -5266,14 +5231,15 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" dependencies = [ "bytes", - "getrandom 0.3.4", + "getrandom 0.4.2", "lru-slab", - "rand 0.9.2", + "rand 0.10.2", + "rand_pcg", "ring", "rustc-hash", "rustls", @@ -5328,9 +5294,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5347,6 +5313,17 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -5385,6 +5362,12 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_distr" version = "0.4.3" @@ -5392,7 +5375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.5", + "rand 0.8.8", ] [[package]] @@ -5405,6 +5388,15 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rand_xoshiro" version = "0.7.0" @@ -5420,7 +5412,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e47a395bdb55442b883c89062d6bcff25dc90fa5f8369af81e0ac6d49d78cf81" dependencies = [ - "ahash 0.8.12", + "ahash", "brotli", "paste", "rand 0.9.2", @@ -5578,22 +5570,13 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - [[package]] name = "reqwest" version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "encoding_rs", "futures-core", @@ -5647,48 +5630,20 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rkyv" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rmcp" -version = "0.1.5" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a0110d28bd076f39e14bfd5b0340216dd18effeb5d02b43215944cc3e5c751" +checksum = "1d1f571c72940a19d9532fe52dbea8bc9912bf1d766c2970bb824056b86f3f59" dependencies = [ - "base64 0.21.7", + "async-trait", + "base64", "chrono", "futures", - "paste", + "pastey", "pin-project-lite", "rmcp-macros", - "schemars 0.8.22", + "schemars 1.2.1", "serde", "serde_json", "thiserror 2.0.18", @@ -5699,12 +5654,14 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "0.1.5" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e2b2fd7497540489fa2db285edd43b7ed14c49157157438664278da6e42a7a" +checksum = "1aad0035b69380782d78ea95b508327e6deaa2235909053e596eea8f27b5e1d5" dependencies = [ + "darling 0.23.0", "proc-macro2", "quote", + "serde_json", "syn 2.0.117", ] @@ -5750,18 +5707,19 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.40.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" +checksum = "7653272e75dcac41dc199fbea6f5797633994fafd339943c06c9af16bf29cd3a" dependencies = [ "arrayvec", "borsh", "bytes", "num-traits", - "rand 0.8.5", - "rkyv", + "rand 0.8.8", + "rand 0.9.2", "serde", "serde_json", + "wasm-bindgen", ] [[package]] @@ -5882,18 +5840,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "schemars" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - [[package]] name = "schemars" version = "0.9.0" @@ -5912,17 +5858,19 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ + "chrono", "dyn-clone", "ref-cast", + "schemars_derive", "serde", "serde_json", ] [[package]] name = "schemars_derive" -version = "0.8.22" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", @@ -6101,12 +6049,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "security-framework" version = "3.7.0" @@ -6245,7 +6187,7 @@ version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ - "base64 0.22.1", + "base64", "chrono", "hex", "indexmap 1.9.3", @@ -6301,7 +6243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -6312,7 +6254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -6547,7 +6489,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ - "base64 0.22.1", + "base64", "bigdecimal", "bytes", "chrono", @@ -6627,7 +6569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", - "base64 0.22.1", + "base64", "bigdecimal", "bitflags 2.11.0", "byteorder", @@ -6651,7 +6593,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand 0.8.5", + "rand 0.8.8", "rsa", "rust_decimal", "serde", @@ -6674,7 +6616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", - "base64 0.22.1", + "base64", "bigdecimal", "bitflags 2.11.0", "byteorder", @@ -6695,7 +6637,7 @@ dependencies = [ "memchr", "num-bigint", "once_cell", - "rand 0.8.5", + "rand 0.8.8", "rust_decimal", "serde", "serde_json", @@ -6897,7 +6839,7 @@ checksum = "64a966cb0e76e311f09cf18507c9af192f15d34886ee43d7ba7c7e3803660c43" dependencies = [ "aho-corasick", "arc-swap", - "base64 0.22.1", + "base64", "bitpacking", "bon", "byteorder", @@ -7777,6 +7719,7 @@ dependencies = [ "cfg-if", "once_cell", "rustversion", + "serde", "wasm-bindgen-macro", "wasm-bindgen-shared", ] @@ -8330,7 +8273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" dependencies = [ "assert-json-diff", - "base64 0.22.1", + "base64", "deadpool", "futures", "http", diff --git a/crates/mcp/Cargo.toml b/crates/mcp/Cargo.toml index b942595b..9594a939 100644 --- a/crates/mcp/Cargo.toml +++ b/crates/mcp/Cargo.toml @@ -24,8 +24,8 @@ serde = { workspace = true } serde_json = { workspace = true } # MCP server framework -rmcp = { version = "0.1", features = ["server", "macros", "transport-io"] } -schemars = "0.8" +rmcp = { version = "1.4", features = ["server", "macros", "transport-io"] } +schemars = "1" # HTTP client for agentd services reqwest = { workspace = true, features = ["json"] } diff --git a/crates/mcp/src/server.rs b/crates/mcp/src/server.rs index e096db60..d9a54370 100644 --- a/crates/mcp/src/server.rs +++ b/crates/mcp/src/server.rs @@ -1,8 +1,8 @@ //! MCP server implementation for agentd. //! -//! `AgentdMcp` is the central server struct. It implements `ServerHandler` -//! via rmcp's `#[tool(tool_box)]` macro, which wires the tool routing into -//! the MCP `tools/list` and `tools/call` handlers. +//! `AgentdMcp` is the central server struct. Its tools are declared in the +//! `#[tool_router]` impl block; `#[tool_handler]` on the `ServerHandler` impl +//! wires them into the MCP `tools/list` and `tools/call` handlers. use crate::client::AgentdClient; use crate::config::AgentdMcpConfig; @@ -11,8 +11,9 @@ use crate::tools::{ metrics, notifications, orchestrator_debug, remediation, workflows, }; use rmcp::{ + handler::server::wrapper::Parameters, model::{ServerCapabilities, ServerInfo}, - tool, ServerHandler, + tool, tool_handler, tool_router, ServerHandler, }; use std::sync::Arc; @@ -25,7 +26,459 @@ pub struct AgentdMcp { client: AgentdClient, } -#[tool(tool_box)] +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct DiagnoseAgentArgs { + /// The agent ID (UUID) to diagnose + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct DiagnoseWorkflowArgs { + /// The workflow ID (UUID) to diagnose + workflow_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct InspectQueueArgs { + /// Queue name (e.g. agent-tasks, workflow-dispatch) + queue_name: String, + /// Number of pending tasks to peek (default: 10, max: 100) + peek_limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetConversationSummaryArgs { + /// The agent ID (UUID) + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListProjectsArgs { + /// Maximum projects to return (default: 50, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetProjectArgs { + /// The project ID (UUID) + project_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListAgentsArgs { + /// Filter by status: pending | running | stopped | failed. Omit for all agents. + status: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetAgentArgs { + /// The agent ID (UUID) to inspect + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetWorkflowArgs { + /// The workflow ID (UUID) to inspect + workflow_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListDispatchesArgs { + /// The workflow ID (UUID) to list dispatches for + workflow_id: String, + /// Filter by status: pending | dispatched | completed | failed | skipped. Omit for all. + status: Option, + /// Maximum number of records to return (default: 20, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetFailedDispatchesArgs { + /// Maximum number of records to return (default: 50, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct CreateAgentArgs { + /// Unique agent name + name: String, + /// Absolute working directory for the agent process + working_dir: String, + /// Model alias or full name (e.g. sonnet, opus, claude-sonnet-4-6). Omit for the default. + model: Option, + /// System prompt for the agent's Claude session + system_prompt: Option, + /// If true, the system prompt is appended to Claude's default prompt instead of replacing it + append_system_prompt: Option, + /// Initial prompt delivered once the agent connects + prompt: Option, + /// Tool policy mode: allow_all | deny_all | require_approval | allow_list | deny_list. Omit for allow_all. + tool_policy_mode: Option, + /// Tool names/patterns for allow_list or deny_list modes + tool_policy_tools: Option>, + /// Communicate room names the agent auto-joins on connect + rooms: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct CreateWorkflowArgs { + /// Workflow name + name: String, + /// ID (UUID) of the agent that receives dispatched prompts — see list_agents + agent_id: String, + /// Trigger configuration object with a `type` field (see tool description for examples) + trigger_config: serde_json::Value, + /// Prompt template dispatched on trigger; {{placeholder}} variables are substituted from the trigger payload + prompt_template: String, + /// Polling interval in seconds for polling triggers (default: 60) + poll_interval_secs: Option, + /// Whether the workflow starts enabled (default: true) + enabled: Option, + /// Tool policy mode applied to dispatched runs: allow_all | deny_all | require_approval | allow_list | deny_list + tool_policy_mode: Option, + /// Tool names/patterns for allow_list or deny_list modes + tool_policy_tools: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct UpdateWorkflowArgs { + /// The workflow ID (UUID) to update + workflow_id: String, + /// New workflow name + name: Option, + /// Reassign to this agent ID (UUID) + agent_id: Option, + /// Replacement trigger configuration object with a `type` field + trigger_config: Option, + /// Replacement prompt template + prompt_template: Option, + /// New polling interval in seconds + poll_interval_secs: Option, + /// Enable or disable the workflow + enabled: Option, + /// Tool policy mode: allow_all | deny_all | require_approval | allow_list | deny_list + tool_policy_mode: Option, + /// Tool names/patterns for allow_list or deny_list modes + tool_policy_tools: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct SetWorkflowEnabledArgs { + /// The workflow ID (UUID) + workflow_id: String, + /// true to enable, false to disable + enabled: bool, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct TriggerWorkflowArgs { + /// The workflow ID (UUID) to trigger + workflow_id: String, + /// Task title substituted into {{title}} + title: Option, + /// Task body substituted into {{body}} + body: Option, + /// Task URL substituted into {{url}} + url: Option, + /// Labels substituted into {{labels}} + labels: Option>, + /// Additional string key/value metadata for {{metadata.*}} placeholders + metadata: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct DeleteWorkflowArgs { + /// The workflow ID (UUID) to delete + workflow_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListNotificationsArgs { + /// Filter by status: pending | viewed | responded | dismissed | expired. Omit for all. + status: Option, + /// Filter by priority: low | normal | high | urgent. Omit for all. + priority: Option, + /// Maximum number to return (default: 20, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetNotificationArgs { + /// The notification ID (UUID) + notification_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct CreateNotificationArgs { + /// Short title for the notification + title: String, + /// Detailed message body with diagnostic context + message: String, + /// Priority level: low | normal | high | urgent (default: normal) + priority: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct DismissNotificationArgs { + /// The notification ID (UUID) to dismiss + notification_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetAgentApprovalsArgs { + /// The agent ID (UUID) whose approvals to list + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ApproveToolRequestArgs { + /// The approval request ID (UUID) to approve + approval_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct DenyToolRequestArgs { + /// The approval request ID (UUID) to deny + approval_id: String, + /// Optional reason for denial, sent back to the agent + reason: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListRoomsArgs { + /// Filter by room type: direct | group | broadcast. Omit for all. + room_type: Option, + /// Filter by project ID (UUID). Omit for all. + project_id: Option, + /// Maximum number of rooms to return (default: 50, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetRoomArgs { + /// The room ID (UUID) to fetch + room_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListMessagesArgs { + /// The room ID (UUID) whose messages to list + room_id: String, + /// Maximum number of messages (default: 20, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct SendRoomMessageArgs { + /// The room ID (UUID) to post into + room_id: String, + /// Sender identifier (agent ID or human username) + sender_id: String, + /// Display name for the sender + sender_name: String, + /// Sender kind: agent | human + sender_kind: String, + /// The message content to send + content: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct RememberArgs { + /// The natural-language content to store (required, non-empty) + content: String, + /// Identity of the actor storing this memory, e.g. your agent name (required) + created_by: String, + /// Memory type: information | question | request (default: information) + memory_type: Option, + /// Free-form tags for later filtering + tags: Option>, + /// Visibility: public | private | shared (default: public) + visibility: Option, + /// Actors allowed to read this memory; required when visibility is `shared` + shared_with: Option>, + /// IDs of related memories this one references + references: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct SearchMemoriesArgs { + /// Search query (required, non-empty) + query: String, + /// Filter results to memories with all of these tags + tags: Option>, + /// Filter by memory type: information | question | request + memory_type: Option, + /// Maximum results (default: 10, max: 100) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ListMemoriesArgs { + /// Filter by memory type: information | question | request + memory_type: Option, + /// Filter by a tag (single tag) + tag: Option, + /// Filter by creator identifier + created_by: Option, + /// Filter by visibility: public | private | shared + visibility: Option, + /// Maximum results (default: 50, max: 200) + limit: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetMemoryArgs { + /// The memory ID (e.g. mem_1718000000000_a1b2c3d4) + memory_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeListDocumentsArgs { + /// Project UUID that owns the documents + project_id: String, + /// Only return documents whose rel_path starts with this prefix, e.g. `docs/` + prefix: Option, + /// Maximum results (default: 50, max: 500) + limit: Option, + /// Pagination offset (default: 0) + offset: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeReadDocumentArgs { + /// Project UUID that owns the document + project_id: String, + /// Document UUID to read + doc_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeCreateDocumentArgs { + /// Project UUID to create the document under + project_id: String, + /// Relative path ending in `.md`, e.g. `docs/readme.md` (no `..`, no absolute paths) + rel_path: String, + /// Initial markdown body content + content: String, + /// Optional title override (defaults to the filename stem) + title: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeUpdateDocumentArgs { + /// Project UUID that owns the document + project_id: String, + /// Document UUID to update + doc_id: String, + /// New markdown body content (replaces the whole body) + content: Option, + /// New title + title: Option, + /// Optimistic concurrency token: the RFC3339 updated_at from a prior read + expected_updated_at: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeDeleteDocumentArgs { + /// Project UUID that owns the document + project_id: String, + /// Document UUID to delete + doc_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct KnowledgeGetTreeArgs { + /// Project UUID whose document tree to render + project_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct RestartAgentArgs { + /// The agent ID (UUID) to restart + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct SendAgentMessageArgs { + /// The agent ID (UUID) to message + agent_id: String, + /// The message content or prompt to send to the agent + message: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct UpdateAgentToolPolicyArgs { + /// The agent ID (UUID) + agent_id: String, + /// Policy mode: allow_all | deny_all | require_approval | allow_list | deny_list + mode: String, + /// Tool name patterns for allow_list or deny_list modes (e.g. ["Bash", "Write"]) + tools: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct TerminateAgentArgs { + /// The agent ID (UUID) to terminate + agent_id: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct UpdateAgentModelArgs { + /// The agent ID (UUID) + agent_id: String, + /// The new model identifier (e.g. claude-opus-4-5, claude-sonnet-4-5) + model: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct RetryFailedDispatchesArgs { + /// The workflow ID (UUID) to retry dispatches for + workflow_id: String, + /// Only retry dispatches that failed within this many hours (default: 24) + hours: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct CleanupStaleDispatchesArgs { + /// Consider dispatches stale after this many hours (default: 2) + stale_hours: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct AutoApproveSafeToolsArgs { + /// Additional tool names to consider safe beyond the default read-only set (e.g. ["LSP", "TaskOutput"]) + additional_safe_tools: Option>, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct ResolveNotificationBacklogArgs { + /// Dismiss low-priority notifications older than this many hours (default: 48) + hours: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct CheckSingleServiceArgs { + /// Service name: orchestrator | communicate | memory | notify | ask | wrap | monitor | hook + service: String, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct GetPrometheusMetricsArgs { + /// Service: orchestrator | notify | memory | communicate | monitor | ask | wrap | hook (default: orchestrator) + service: Option, +} + +#[derive(Debug, serde::Deserialize, schemars::JsonSchema)] +struct QueryMetricsArgs { + /// Catalog query name; omit to list the catalog + name: Option, + /// Time window for rate/increase queries, e.g. 15m, 1h, 24h + window: Option, + /// true for a range query (trend over the last 6h) instead of an instant value + range: Option, +} + +#[tool_router] impl AgentdMcp { /// Create a new server instance from the given configuration. pub fn new(config: AgentdMcpConfig) -> Self { @@ -41,10 +494,9 @@ impl AgentdMcp { )] async fn diagnose_agent( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) to diagnose")] - agent_id: String, + Parameters(diagnose_agent_args): Parameters, ) -> String { + let DiagnoseAgentArgs { agent_id } = diagnose_agent_args; diagnostic::run_diagnose_agent(&self.client, &agent_id).await } @@ -55,10 +507,9 @@ impl AgentdMcp { )] async fn diagnose_workflow( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to diagnose")] - workflow_id: String, + Parameters(diagnose_workflow_args): Parameters, ) -> String { + let DiagnoseWorkflowArgs { workflow_id } = diagnose_workflow_args; diagnostic::run_diagnose_workflow(&self.client, &workflow_id).await } @@ -85,13 +536,9 @@ impl AgentdMcp { )] async fn inspect_queue( &self, - #[tool(param)] - #[schemars(description = "Queue name (e.g. agent-tasks, workflow-dispatch)")] - queue_name: String, - #[tool(param)] - #[schemars(description = "Number of pending tasks to peek (default: 10, max: 100)")] - peek_limit: Option, + Parameters(inspect_queue_args): Parameters, ) -> String { + let InspectQueueArgs { queue_name, peek_limit } = inspect_queue_args; orchestrator_debug::run_inspect_queue(&self.client, &queue_name, peek_limit).await } @@ -101,10 +548,9 @@ impl AgentdMcp { )] async fn get_conversation_summary( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID)")] - agent_id: String, + Parameters(get_conversation_summary_args): Parameters, ) -> String { + let GetConversationSummaryArgs { agent_id } = get_conversation_summary_args; orchestrator_debug::run_get_conversation_summary(&self.client, &agent_id).await } @@ -114,10 +560,9 @@ impl AgentdMcp { )] async fn list_projects( &self, - #[tool(param)] - #[schemars(description = "Maximum projects to return (default: 50, max: 200)")] - limit: Option, + Parameters(list_projects_args): Parameters, ) -> String { + let ListProjectsArgs { limit } = list_projects_args; orchestrator_debug::run_list_projects(&self.client, limit).await } @@ -127,10 +572,9 @@ impl AgentdMcp { )] async fn get_project( &self, - #[tool(param)] - #[schemars(description = "The project ID (UUID)")] - project_id: String, + Parameters(get_project_args): Parameters, ) -> String { + let GetProjectArgs { project_id } = get_project_args; orchestrator_debug::run_get_project(&self.client, &project_id).await } @@ -142,12 +586,9 @@ impl AgentdMcp { )] async fn list_agents( &self, - #[tool(param)] - #[schemars( - description = "Filter by status: pending | running | stopped | failed. Omit for all agents." - )] - status: Option, + Parameters(list_agents_args): Parameters, ) -> String { + let ListAgentsArgs { status } = list_agents_args; agents::run_list_agents(&self.client, status.as_deref()).await } @@ -155,12 +596,8 @@ impl AgentdMcp { #[tool( description = "Get detailed information about a specific agent including its configuration, tool policy, model, working directory, and environment variable keys (values are redacted)." )] - async fn get_agent( - &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) to inspect")] - agent_id: String, - ) -> String { + async fn get_agent(&self, Parameters(get_agent_args): Parameters) -> String { + let GetAgentArgs { agent_id } = get_agent_args; agents::run_get_agent(&self.client, &agent_id).await } @@ -188,10 +625,9 @@ impl AgentdMcp { )] async fn get_workflow( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to inspect")] - workflow_id: String, + Parameters(get_workflow_args): Parameters, ) -> String { + let GetWorkflowArgs { workflow_id } = get_workflow_args; workflows::run_get_workflow(&self.client, &workflow_id).await } @@ -201,18 +637,9 @@ impl AgentdMcp { )] async fn list_dispatches( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to list dispatches for")] - workflow_id: String, - #[tool(param)] - #[schemars( - description = "Filter by status: pending | dispatched | completed | failed | skipped. Omit for all." - )] - status: Option, - #[tool(param)] - #[schemars(description = "Maximum number of records to return (default: 20, max: 200)")] - limit: Option, + Parameters(list_dispatches_args): Parameters, ) -> String { + let ListDispatchesArgs { workflow_id, status, limit } = list_dispatches_args; workflows::run_list_dispatches(&self.client, &workflow_id, status.as_deref(), limit).await } @@ -222,10 +649,9 @@ impl AgentdMcp { )] async fn get_failed_dispatches( &self, - #[tool(param)] - #[schemars(description = "Maximum number of records to return (default: 50, max: 200)")] - limit: Option, + Parameters(get_failed_dispatches_args): Parameters, ) -> String { + let GetFailedDispatchesArgs { limit } = get_failed_dispatches_args; workflows::run_get_failed_dispatches(&self.client, limit).await } @@ -235,43 +661,21 @@ impl AgentdMcp { #[tool( description = "Create a new agent. Exposes the safe subset of agent configuration: name, working_dir, model, system_prompt, initial prompt, tool policy, and rooms. Env vars and Docker settings are deliberately NOT exposed (secrets must not transit MCP) — use the CLI for those. Returns the new agent ID." )] - #[allow(clippy::too_many_arguments)] async fn create_agent( &self, - #[tool(param)] - #[schemars(description = "Unique agent name")] - name: String, - #[tool(param)] - #[schemars(description = "Absolute working directory for the agent process")] - working_dir: String, - #[tool(param)] - #[schemars( - description = "Model alias or full name (e.g. sonnet, opus, claude-sonnet-4-6). Omit for the default." - )] - model: Option, - #[tool(param)] - #[schemars(description = "System prompt for the agent's Claude session")] - system_prompt: Option, - #[tool(param)] - #[schemars( - description = "If true, the system prompt is appended to Claude's default prompt instead of replacing it" - )] - append_system_prompt: Option, - #[tool(param)] - #[schemars(description = "Initial prompt delivered once the agent connects")] - prompt: Option, - #[tool(param)] - #[schemars( - description = "Tool policy mode: allow_all | deny_all | require_approval | allow_list | deny_list. Omit for allow_all." - )] - tool_policy_mode: Option, - #[tool(param)] - #[schemars(description = "Tool names/patterns for allow_list or deny_list modes")] - tool_policy_tools: Option>, - #[tool(param)] - #[schemars(description = "Communicate room names the agent auto-joins on connect")] - rooms: Option>, + Parameters(create_agent_args): Parameters, ) -> String { + let CreateAgentArgs { + name, + working_dir, + model, + system_prompt, + append_system_prompt, + prompt, + tool_policy_mode, + tool_policy_tools, + rooms, + } = create_agent_args; creation::run_create_agent( &self.client, &name, @@ -291,42 +695,20 @@ impl AgentdMcp { #[tool( description = "Create a new workflow that dispatches prompts to an agent when its trigger fires. trigger_config is a JSON object with a `type` field, e.g. {\"type\":\"cron\",\"expression\":\"0 9 * * MON-FRI\"}, {\"type\":\"manual\"}, or {\"type\":\"agent_idle\",\"idle_seconds\":600}. Valid types: github_issues, github_pull_requests, cron, delay, agent_lifecycle, dispatch_result, webhook, manual, agent_idle, linear_issues, composite, queue, ask_response, gitlab_issues, gitlab_merge_requests. Use get_workflow on an existing workflow to copy a working config. prompt_template supports {{placeholder}} substitution and is validated server-side." )] - #[allow(clippy::too_many_arguments)] async fn create_workflow( &self, - #[tool(param)] - #[schemars(description = "Workflow name")] - name: String, - #[tool(param)] - #[schemars( - description = "ID (UUID) of the agent that receives dispatched prompts — see list_agents" - )] - agent_id: String, - #[tool(param)] - #[schemars( - description = "Trigger configuration object with a `type` field (see tool description for examples)" - )] - trigger_config: serde_json::Value, - #[tool(param)] - #[schemars( - description = "Prompt template dispatched on trigger; {{placeholder}} variables are substituted from the trigger payload" - )] - prompt_template: String, - #[tool(param)] - #[schemars(description = "Polling interval in seconds for polling triggers (default: 60)")] - poll_interval_secs: Option, - #[tool(param)] - #[schemars(description = "Whether the workflow starts enabled (default: true)")] - enabled: Option, - #[tool(param)] - #[schemars( - description = "Tool policy mode applied to dispatched runs: allow_all | deny_all | require_approval | allow_list | deny_list" - )] - tool_policy_mode: Option, - #[tool(param)] - #[schemars(description = "Tool names/patterns for allow_list or deny_list modes")] - tool_policy_tools: Option>, + Parameters(create_workflow_args): Parameters, ) -> String { + let CreateWorkflowArgs { + name, + agent_id, + trigger_config, + prompt_template, + poll_interval_secs, + enabled, + tool_policy_mode, + tool_policy_tools, + } = create_workflow_args; creation::run_create_workflow( &self.client, &name, @@ -345,39 +727,21 @@ impl AgentdMcp { #[tool( description = "Update an existing workflow. Only the provided fields change (merge semantics): name, agent_id, trigger_config, prompt_template, poll_interval_secs, enabled, tool policy. Use set_workflow_enabled for a plain enable/disable toggle." )] - #[allow(clippy::too_many_arguments)] async fn update_workflow( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to update")] - workflow_id: String, - #[tool(param)] - #[schemars(description = "New workflow name")] - name: Option, - #[tool(param)] - #[schemars(description = "Reassign to this agent ID (UUID)")] - agent_id: Option, - #[tool(param)] - #[schemars(description = "Replacement trigger configuration object with a `type` field")] - trigger_config: Option, - #[tool(param)] - #[schemars(description = "Replacement prompt template")] - prompt_template: Option, - #[tool(param)] - #[schemars(description = "New polling interval in seconds")] - poll_interval_secs: Option, - #[tool(param)] - #[schemars(description = "Enable or disable the workflow")] - enabled: Option, - #[tool(param)] - #[schemars( - description = "Tool policy mode: allow_all | deny_all | require_approval | allow_list | deny_list" - )] - tool_policy_mode: Option, - #[tool(param)] - #[schemars(description = "Tool names/patterns for allow_list or deny_list modes")] - tool_policy_tools: Option>, + Parameters(update_workflow_args): Parameters, ) -> String { + let UpdateWorkflowArgs { + workflow_id, + name, + agent_id, + trigger_config, + prompt_template, + poll_interval_secs, + enabled, + tool_policy_mode, + tool_policy_tools, + } = update_workflow_args; creation::run_update_workflow( &self.client, &workflow_id, @@ -399,13 +763,9 @@ impl AgentdMcp { )] async fn set_workflow_enabled( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID)")] - workflow_id: String, - #[tool(param)] - #[schemars(description = "true to enable, false to disable")] - enabled: bool, + Parameters(set_workflow_enabled_args): Parameters, ) -> String { + let SetWorkflowEnabledArgs { workflow_id, enabled } = set_workflow_enabled_args; creation::run_set_workflow_enabled(&self.client, &workflow_id, enabled).await } @@ -415,27 +775,10 @@ impl AgentdMcp { )] async fn trigger_workflow( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to trigger")] - workflow_id: String, - #[tool(param)] - #[schemars(description = "Task title substituted into {{title}}")] - title: Option, - #[tool(param)] - #[schemars(description = "Task body substituted into {{body}}")] - body: Option, - #[tool(param)] - #[schemars(description = "Task URL substituted into {{url}}")] - url: Option, - #[tool(param)] - #[schemars(description = "Labels substituted into {{labels}}")] - labels: Option>, - #[tool(param)] - #[schemars( - description = "Additional string key/value metadata for {{metadata.*}} placeholders" - )] - metadata: Option, + Parameters(trigger_workflow_args): Parameters, ) -> String { + let TriggerWorkflowArgs { workflow_id, title, body, url, labels, metadata } = + trigger_workflow_args; creation::run_trigger_workflow( &self.client, &workflow_id, @@ -454,10 +797,9 @@ impl AgentdMcp { )] async fn delete_workflow( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to delete")] - workflow_id: String, + Parameters(delete_workflow_args): Parameters, ) -> String { + let DeleteWorkflowArgs { workflow_id } = delete_workflow_args; creation::run_delete_workflow(&self.client, &workflow_id).await } @@ -469,20 +811,9 @@ impl AgentdMcp { )] async fn list_notifications( &self, - #[tool(param)] - #[schemars( - description = "Filter by status: pending | viewed | responded | dismissed | expired. Omit for all." - )] - status: Option, - #[tool(param)] - #[schemars( - description = "Filter by priority: low | normal | high | urgent. Omit for all." - )] - priority: Option, - #[tool(param)] - #[schemars(description = "Maximum number to return (default: 20, max: 200)")] - limit: Option, + Parameters(list_notifications_args): Parameters, ) -> String { + let ListNotificationsArgs { status, priority, limit } = list_notifications_args; notifications::run_list_notifications( &self.client, status.as_deref(), @@ -498,10 +829,9 @@ impl AgentdMcp { )] async fn get_notification( &self, - #[tool(param)] - #[schemars(description = "The notification ID (UUID)")] - notification_id: String, + Parameters(get_notification_args): Parameters, ) -> String { + let GetNotificationArgs { notification_id } = get_notification_args; notifications::run_get_notification(&self.client, ¬ification_id).await } @@ -519,16 +849,9 @@ impl AgentdMcp { )] async fn create_notification( &self, - #[tool(param)] - #[schemars(description = "Short title for the notification")] - title: String, - #[tool(param)] - #[schemars(description = "Detailed message body with diagnostic context")] - message: String, - #[tool(param)] - #[schemars(description = "Priority level: low | normal | high | urgent (default: normal)")] - priority: Option, + Parameters(create_notification_args): Parameters, ) -> String { + let CreateNotificationArgs { title, message, priority } = create_notification_args; notifications::run_create_notification(&self.client, &title, &message, priority.as_deref()) .await } @@ -539,10 +862,9 @@ impl AgentdMcp { )] async fn dismiss_notification( &self, - #[tool(param)] - #[schemars(description = "The notification ID (UUID) to dismiss")] - notification_id: String, + Parameters(dismiss_notification_args): Parameters, ) -> String { + let DismissNotificationArgs { notification_id } = dismiss_notification_args; notifications::run_dismiss_notification(&self.client, ¬ification_id).await } @@ -562,10 +884,9 @@ impl AgentdMcp { )] async fn get_agent_approvals( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) whose approvals to list")] - agent_id: String, + Parameters(get_agent_approvals_args): Parameters, ) -> String { + let GetAgentApprovalsArgs { agent_id } = get_agent_approvals_args; approvals::run_get_agent_approvals(&self.client, &agent_id).await } @@ -575,10 +896,9 @@ impl AgentdMcp { )] async fn approve_tool_request( &self, - #[tool(param)] - #[schemars(description = "The approval request ID (UUID) to approve")] - approval_id: String, + Parameters(approve_tool_request_args): Parameters, ) -> String { + let ApproveToolRequestArgs { approval_id } = approve_tool_request_args; approvals::run_approve_tool_request(&self.client, &approval_id).await } @@ -588,13 +908,9 @@ impl AgentdMcp { )] async fn deny_tool_request( &self, - #[tool(param)] - #[schemars(description = "The approval request ID (UUID) to deny")] - approval_id: String, - #[tool(param)] - #[schemars(description = "Optional reason for denial, sent back to the agent")] - reason: Option, + Parameters(deny_tool_request_args): Parameters, ) -> String { + let DenyToolRequestArgs { approval_id, reason } = deny_tool_request_args; approvals::run_deny_tool_request(&self.client, &approval_id, reason.as_deref()).await } @@ -604,18 +920,8 @@ impl AgentdMcp { #[tool( description = "List rooms in the communicate service. Optionally filter by room_type (direct | group | broadcast) or project_id. Returns a table with type, name, ID, topic, and creation time." )] - async fn list_rooms( - &self, - #[tool(param)] - #[schemars(description = "Filter by room type: direct | group | broadcast. Omit for all.")] - room_type: Option, - #[tool(param)] - #[schemars(description = "Filter by project ID (UUID). Omit for all.")] - project_id: Option, - #[tool(param)] - #[schemars(description = "Maximum number of rooms to return (default: 50, max: 200)")] - limit: Option, - ) -> String { + async fn list_rooms(&self, Parameters(list_rooms_args): Parameters) -> String { + let ListRoomsArgs { room_type, project_id, limit } = list_rooms_args; communicate::run_list_rooms( &self.client, room_type.as_deref(), @@ -629,12 +935,8 @@ impl AgentdMcp { #[tool( description = "Get a room's metadata and full participant list. Useful for understanding who's in a room and what its purpose is." )] - async fn get_room( - &self, - #[tool(param)] - #[schemars(description = "The room ID (UUID) to fetch")] - room_id: String, - ) -> String { + async fn get_room(&self, Parameters(get_room_args): Parameters) -> String { + let GetRoomArgs { room_id } = get_room_args; communicate::run_get_room(&self.client, &room_id).await } @@ -644,13 +946,9 @@ impl AgentdMcp { )] async fn list_messages( &self, - #[tool(param)] - #[schemars(description = "The room ID (UUID) whose messages to list")] - room_id: String, - #[tool(param)] - #[schemars(description = "Maximum number of messages (default: 20, max: 200)")] - limit: Option, + Parameters(list_messages_args): Parameters, ) -> String { + let ListMessagesArgs { room_id, limit } = list_messages_args; communicate::run_list_messages(&self.client, &room_id, limit).await } @@ -660,22 +958,10 @@ impl AgentdMcp { )] async fn send_room_message( &self, - #[tool(param)] - #[schemars(description = "The room ID (UUID) to post into")] - room_id: String, - #[tool(param)] - #[schemars(description = "Sender identifier (agent ID or human username)")] - sender_id: String, - #[tool(param)] - #[schemars(description = "Display name for the sender")] - sender_name: String, - #[tool(param)] - #[schemars(description = "Sender kind: agent | human")] - sender_kind: String, - #[tool(param)] - #[schemars(description = "The message content to send")] - content: String, + Parameters(send_room_message_args): Parameters, ) -> String { + let SendRoomMessageArgs { room_id, sender_id, sender_name, sender_kind, content } = + send_room_message_args; communicate::run_send_room_message( &self.client, &room_id, @@ -693,37 +979,16 @@ impl AgentdMcp { #[tool( description = "Store a new memory in the shared agent memory service. The content is embedded for later semantic search. Use this to persist a fact, decision, open question, or request so it survives across sessions and is discoverable by other agents. `created_by` should be your own agent identity. Defaults: type=information, visibility=public." )] - #[allow(clippy::too_many_arguments)] - async fn remember( - &self, - #[tool(param)] - #[schemars(description = "The natural-language content to store (required, non-empty)")] - content: String, - #[tool(param)] - #[schemars( - description = "Identity of the actor storing this memory, e.g. your agent name (required)" - )] - created_by: String, - #[tool(param)] - #[schemars( - description = "Memory type: information | question | request (default: information)" - )] - memory_type: Option, - #[tool(param)] - #[schemars(description = "Free-form tags for later filtering")] - tags: Option>, - #[tool(param)] - #[schemars(description = "Visibility: public | private | shared (default: public)")] - visibility: Option, - #[tool(param)] - #[schemars( - description = "Actors allowed to read this memory; required when visibility is `shared`" - )] - shared_with: Option>, - #[tool(param)] - #[schemars(description = "IDs of related memories this one references")] - references: Option>, - ) -> String { + async fn remember(&self, Parameters(remember_args): Parameters) -> String { + let RememberArgs { + content, + created_by, + memory_type, + tags, + visibility, + shared_with, + references, + } = remember_args; memory::run_create_memory( &self.client, &content, @@ -743,19 +1008,9 @@ impl AgentdMcp { )] async fn search_memories( &self, - #[tool(param)] - #[schemars(description = "Search query (required, non-empty)")] - query: String, - #[tool(param)] - #[schemars(description = "Filter results to memories with all of these tags")] - tags: Option>, - #[tool(param)] - #[schemars(description = "Filter by memory type: information | question | request")] - memory_type: Option, - #[tool(param)] - #[schemars(description = "Maximum results (default: 10, max: 100)")] - limit: Option, + Parameters(search_memories_args): Parameters, ) -> String { + let SearchMemoriesArgs { query, tags, memory_type, limit } = search_memories_args; memory::run_search_memories(&self.client, &query, tags, memory_type.as_deref(), limit).await } @@ -765,22 +1020,10 @@ impl AgentdMcp { )] async fn list_memories( &self, - #[tool(param)] - #[schemars(description = "Filter by memory type: information | question | request")] - memory_type: Option, - #[tool(param)] - #[schemars(description = "Filter by a tag (single tag)")] - tag: Option, - #[tool(param)] - #[schemars(description = "Filter by creator identifier")] - created_by: Option, - #[tool(param)] - #[schemars(description = "Filter by visibility: public | private | shared")] - visibility: Option, - #[tool(param)] - #[schemars(description = "Maximum results (default: 50, max: 200)")] - limit: Option, + Parameters(list_memories_args): Parameters, ) -> String { + let ListMemoriesArgs { memory_type, tag, created_by, visibility, limit } = + list_memories_args; memory::run_list_memories( &self.client, memory_type.as_deref(), @@ -796,12 +1039,8 @@ impl AgentdMcp { #[tool( description = "Fetch a single memory by its ID, including full content, tags, visibility, references, and sharing list." )] - async fn get_memory( - &self, - #[tool(param)] - #[schemars(description = "The memory ID (e.g. mem_1718000000000_a1b2c3d4)")] - memory_id: String, - ) -> String { + async fn get_memory(&self, Parameters(get_memory_args): Parameters) -> String { + let GetMemoryArgs { memory_id } = get_memory_args; memory::run_get_memory(&self.client, &memory_id).await } @@ -813,21 +1052,10 @@ impl AgentdMcp { )] async fn knowledge_list_documents( &self, - #[tool(param)] - #[schemars(description = "Project UUID that owns the documents")] - project_id: String, - #[tool(param)] - #[schemars( - description = "Only return documents whose rel_path starts with this prefix, e.g. `docs/`" - )] - prefix: Option, - #[tool(param)] - #[schemars(description = "Maximum results (default: 50, max: 500)")] - limit: Option, - #[tool(param)] - #[schemars(description = "Pagination offset (default: 0)")] - offset: Option, + Parameters(knowledge_list_documents_args): Parameters, ) -> String { + let KnowledgeListDocumentsArgs { project_id, prefix, limit, offset } = + knowledge_list_documents_args; knowledge::run_list_documents(&self.client, &project_id, prefix.as_deref(), limit, offset) .await } @@ -838,13 +1066,9 @@ impl AgentdMcp { )] async fn knowledge_read_document( &self, - #[tool(param)] - #[schemars(description = "Project UUID that owns the document")] - project_id: String, - #[tool(param)] - #[schemars(description = "Document UUID to read")] - doc_id: String, + Parameters(knowledge_read_document_args): Parameters, ) -> String { + let KnowledgeReadDocumentArgs { project_id, doc_id } = knowledge_read_document_args; knowledge::run_read_document(&self.client, &project_id, &doc_id).await } @@ -854,21 +1078,10 @@ impl AgentdMcp { )] async fn knowledge_create_document( &self, - #[tool(param)] - #[schemars(description = "Project UUID to create the document under")] - project_id: String, - #[tool(param)] - #[schemars( - description = "Relative path ending in `.md`, e.g. `docs/readme.md` (no `..`, no absolute paths)" - )] - rel_path: String, - #[tool(param)] - #[schemars(description = "Initial markdown body content")] - content: String, - #[tool(param)] - #[schemars(description = "Optional title override (defaults to the filename stem)")] - title: Option, + Parameters(knowledge_create_document_args): Parameters, ) -> String { + let KnowledgeCreateDocumentArgs { project_id, rel_path, content, title } = + knowledge_create_document_args; knowledge::run_create_document( &self.client, &project_id, @@ -885,24 +1098,10 @@ impl AgentdMcp { )] async fn knowledge_update_document( &self, - #[tool(param)] - #[schemars(description = "Project UUID that owns the document")] - project_id: String, - #[tool(param)] - #[schemars(description = "Document UUID to update")] - doc_id: String, - #[tool(param)] - #[schemars(description = "New markdown body content (replaces the whole body)")] - content: Option, - #[tool(param)] - #[schemars(description = "New title")] - title: Option, - #[tool(param)] - #[schemars( - description = "Optimistic concurrency token: the RFC3339 updated_at from a prior read" - )] - expected_updated_at: Option, + Parameters(knowledge_update_document_args): Parameters, ) -> String { + let KnowledgeUpdateDocumentArgs { project_id, doc_id, content, title, expected_updated_at } = + knowledge_update_document_args; knowledge::run_update_document( &self.client, &project_id, @@ -920,13 +1119,9 @@ impl AgentdMcp { )] async fn knowledge_delete_document( &self, - #[tool(param)] - #[schemars(description = "Project UUID that owns the document")] - project_id: String, - #[tool(param)] - #[schemars(description = "Document UUID to delete")] - doc_id: String, + Parameters(knowledge_delete_document_args): Parameters, ) -> String { + let KnowledgeDeleteDocumentArgs { project_id, doc_id } = knowledge_delete_document_args; knowledge::run_delete_document(&self.client, &project_id, &doc_id).await } @@ -936,10 +1131,9 @@ impl AgentdMcp { )] async fn knowledge_get_tree( &self, - #[tool(param)] - #[schemars(description = "Project UUID whose document tree to render")] - project_id: String, + Parameters(knowledge_get_tree_args): Parameters, ) -> String { + let KnowledgeGetTreeArgs { project_id } = knowledge_get_tree_args; knowledge::run_get_tree(&self.client, &project_id).await } @@ -953,10 +1147,9 @@ impl AgentdMcp { )] async fn restart_agent( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) to restart")] - agent_id: String, + Parameters(restart_agent_args): Parameters, ) -> String { + let RestartAgentArgs { agent_id } = restart_agent_args; lifecycle::run_restart_agent(&self.client, &agent_id).await } @@ -966,13 +1159,9 @@ impl AgentdMcp { )] async fn send_agent_message( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) to message")] - agent_id: String, - #[tool(param)] - #[schemars(description = "The message content or prompt to send to the agent")] - message: String, + Parameters(send_agent_message_args): Parameters, ) -> String { + let SendAgentMessageArgs { agent_id, message } = send_agent_message_args; lifecycle::run_send_agent_message(&self.client, &agent_id, &message).await } @@ -982,20 +1171,9 @@ impl AgentdMcp { )] async fn update_agent_tool_policy( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID)")] - agent_id: String, - #[tool(param)] - #[schemars( - description = "Policy mode: allow_all | deny_all | require_approval | allow_list | deny_list" - )] - mode: String, - #[tool(param)] - #[schemars( - description = "Tool name patterns for allow_list or deny_list modes (e.g. [\"Bash\", \"Write\"])" - )] - tools: Option>, + Parameters(update_agent_tool_policy_args): Parameters, ) -> String { + let UpdateAgentToolPolicyArgs { agent_id, mode, tools } = update_agent_tool_policy_args; lifecycle::run_update_agent_tool_policy(&self.client, &agent_id, &mode, tools).await } @@ -1007,10 +1185,9 @@ impl AgentdMcp { )] async fn terminate_agent( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID) to terminate")] - agent_id: String, + Parameters(terminate_agent_args): Parameters, ) -> String { + let TerminateAgentArgs { agent_id } = terminate_agent_args; lifecycle::run_terminate_agent(&self.client, &agent_id).await } @@ -1020,15 +1197,9 @@ impl AgentdMcp { )] async fn update_agent_model( &self, - #[tool(param)] - #[schemars(description = "The agent ID (UUID)")] - agent_id: String, - #[tool(param)] - #[schemars( - description = "The new model identifier (e.g. claude-opus-4-5, claude-sonnet-4-5)" - )] - model: String, + Parameters(update_agent_model_args): Parameters, ) -> String { + let UpdateAgentModelArgs { agent_id, model } = update_agent_model_args; lifecycle::run_update_agent_model(&self.client, &agent_id, &model).await } @@ -1048,15 +1219,9 @@ impl AgentdMcp { )] async fn retry_failed_dispatches( &self, - #[tool(param)] - #[schemars(description = "The workflow ID (UUID) to retry dispatches for")] - workflow_id: String, - #[tool(param)] - #[schemars( - description = "Only retry dispatches that failed within this many hours (default: 24)" - )] - hours: Option, + Parameters(retry_failed_dispatches_args): Parameters, ) -> String { + let RetryFailedDispatchesArgs { workflow_id, hours } = retry_failed_dispatches_args; remediation::run_retry_failed_dispatches(&self.client, &workflow_id, hours).await } @@ -1066,10 +1231,9 @@ impl AgentdMcp { )] async fn cleanup_stale_dispatches( &self, - #[tool(param)] - #[schemars(description = "Consider dispatches stale after this many hours (default: 2)")] - stale_hours: Option, + Parameters(cleanup_stale_dispatches_args): Parameters, ) -> String { + let CleanupStaleDispatchesArgs { stale_hours } = cleanup_stale_dispatches_args; remediation::run_cleanup_stale_dispatches(&self.client, stale_hours).await } @@ -1079,12 +1243,9 @@ impl AgentdMcp { )] async fn auto_approve_safe_tools( &self, - #[tool(param)] - #[schemars( - description = "Additional tool names to consider safe beyond the default read-only set (e.g. [\"LSP\", \"TaskOutput\"])" - )] - additional_safe_tools: Option>, + Parameters(auto_approve_safe_tools_args): Parameters, ) -> String { + let AutoApproveSafeToolsArgs { additional_safe_tools } = auto_approve_safe_tools_args; remediation::run_auto_approve_safe_tools(&self.client, additional_safe_tools).await } @@ -1094,12 +1255,9 @@ impl AgentdMcp { )] async fn resolve_notification_backlog( &self, - #[tool(param)] - #[schemars( - description = "Dismiss low-priority notifications older than this many hours (default: 48)" - )] - hours: Option, + Parameters(resolve_notification_backlog_args): Parameters, ) -> String { + let ResolveNotificationBacklogArgs { hours } = resolve_notification_backlog_args; remediation::run_resolve_notification_backlog(&self.client, hours).await } @@ -1119,12 +1277,9 @@ impl AgentdMcp { )] async fn check_single_service( &self, - #[tool(param)] - #[schemars( - description = "Service name: orchestrator | communicate | memory | notify | ask | wrap | monitor | hook" - )] - service: String, + Parameters(check_single_service_args): Parameters, ) -> String { + let CheckSingleServiceArgs { service } = check_single_service_args; health::run_check_single_service(&self.client, &service).await } @@ -1142,12 +1297,9 @@ impl AgentdMcp { )] async fn get_prometheus_metrics( &self, - #[tool(param)] - #[schemars( - description = "Service: orchestrator | notify | memory | communicate | monitor | ask | wrap | hook (default: orchestrator)" - )] - service: Option, + Parameters(get_prometheus_metrics_args): Parameters, ) -> String { + let GetPrometheusMetricsArgs { service } = get_prometheus_metrics_args; health::run_get_prometheus_metrics(&self.client, service.as_deref()).await } @@ -1157,18 +1309,9 @@ impl AgentdMcp { )] async fn query_metrics( &self, - #[tool(param)] - #[schemars(description = "Catalog query name; omit to list the catalog")] - name: Option, - #[tool(param)] - #[schemars(description = "Time window for rate/increase queries, e.g. 15m, 1h, 24h")] - window: Option, - #[tool(param)] - #[schemars( - description = "true for a range query (trend over the last 6h) instead of an instant value" - )] - range: Option, + Parameters(query_metrics_args): Parameters, ) -> String { + let QueryMetricsArgs { name, window, range } = query_metrics_args; metrics::run_query_metrics( &self.client, name.as_deref(), @@ -1179,12 +1322,11 @@ impl AgentdMcp { } } -#[tool(tool_box)] +#[tool_handler] impl ServerHandler for AgentdMcp { fn get_info(&self) -> ServerInfo { - ServerInfo { - instructions: Some( - "agentd MCP server — exposes agentd agent management, \ + ServerInfo::new(ServerCapabilities::builder().enable_tools().build()).with_instructions( + "agentd MCP server — exposes agentd agent management, \ messaging, memory, knowledge, notification, approval, \ workflow, and diagnostic services as MCP tools. \ Start with `diagnose_system` or `check_service_health` for a \ @@ -1192,11 +1334,7 @@ impl ServerHandler for AgentdMcp { subtle agent stuckness. Provision resources with \ `create_agent` and `create_workflow`; smoke-test new \ workflows with `trigger_workflow`. Browse and author \ - per-project documents with the `knowledge_*` tools." - .into(), - ), - capabilities: ServerCapabilities::builder().enable_tools().build(), - ..Default::default() - } + per-project documents with the `knowledge_*` tools.", + ) } }