diff --git a/.changesets/feat_locay_add_mcp_proxy_crate.md b/.changesets/feat_locay_add_mcp_proxy_crate.md new file mode 100644 index 00000000..f48f2b06 --- /dev/null +++ b/.changesets/feat_locay_add_mcp_proxy_crate.md @@ -0,0 +1,3 @@ +### Built-in basic proxy support via a apollo-mcp-proxy support - @alocay PR #193 + +Adding the apollo-mcp-proxy crate that provides really basic proxy support (only over streamable-http) so using tools like remote-mcp isn't required for basic local testing. diff --git a/Cargo.lock b/Cargo.lock index 2d76b142..6711000e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,12 +46,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -119,9 +113,9 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "apollo-compiler" -version = "1.29.0" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4369d2ac382b0752cc5ff8cdb020e7a3c74480e7d940fc99f139281f8701fb81" +checksum = "87e4c0116cde9e3e5679806cf91c464d9efb7f1e231abffc505e0f6d4b911260" dependencies = [ "ahash", "apollo-parser", @@ -131,20 +125,22 @@ dependencies = [ "rowan", "serde", "serde_json_bytes", - "thiserror 2.0.14", + "thiserror 2.0.16", "triomphe", "typed-arena", ] [[package]] name = "apollo-federation" -version = "2.5.0" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbea4f0fcfcd95ec6f03c41a104488f66eafb37d05bd304a219702d1814449c5" +checksum = "51cbd2e96207f23d680fcf403990173abc7256d27dd7462e4d045e2d06788bdf" dependencies = [ "apollo-compiler", + "countmap", "derive_more", "either", + "encoding_rs", "form_urlencoded", "hashbrown 0.15.5", "http", @@ -167,12 +163,28 @@ dependencies = [ "shape", "strum", "strum_macros", - "thiserror 2.0.14", + "thiserror 2.0.16", "time", "tracing", "url", ] +[[package]] +name = "apollo-mcp-proxy" +version = "0.7.5" +dependencies = [ + "axum", + "clap", + "futures", + "rmcp", + "serde_json", + "tokio", + "tokio-util", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + [[package]] name = "apollo-mcp-registry" version = "0.7.5" @@ -188,7 +200,7 @@ dependencies = [ "serde", "serde_json", "test-log", - "thiserror 2.0.14", + "thiserror 2.0.16", "tokio", "tokio-stream", "tower", @@ -208,6 +220,7 @@ dependencies = [ "anyhow", "apollo-compiler", "apollo-federation", + "apollo-mcp-proxy", "apollo-mcp-registry", "apollo-schema-index", "axum", @@ -233,7 +246,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.14", + "thiserror 2.0.16", "tokio", "tokio-util", "tower-http", @@ -265,7 +278,7 @@ dependencies = [ "itertools", "rstest", "tantivy", - "thiserror 2.0.14", + "thiserror 2.0.16", "tracing", ] @@ -298,13 +311,13 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddb939d66e4ae03cee6091612804ba446b12878410cfa17f785f4dd67d4014e8" +checksum = "977eb15ea9efd848bb8a4a1a2500347ed7f0bf794edf0dc3ddcf439f43d36b23" dependencies = [ - "flate2", + "compression-codecs", + "compression-core", "futures-core", - "memchr", "pin-project-lite", "tokio", ] @@ -317,7 +330,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -462,9 +475,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "bitpacking" @@ -486,9 +499,9 @@ dependencies = [ [[package]] name = "bon" -version = "3.7.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a0c21249ad725ebcadcb1b1885f8e3d56e8e6b8924f560268aab000982d637" +checksum = "c2529c31017402be841eb45892278a6c21a000c0a17643af326c73a73f83f0fb" dependencies = [ "bon-macros", "rustversion", @@ -496,17 +509,17 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.7.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a660ebdea4d4d3ec7788cfc9c035b66efb66028b9b97bf6cde7023ccc8e77e28" +checksum = "d82020dadcb845a345591863adb65d74fa8dc5c18a0b6d408470e13b7adc7005" dependencies = [ - "darling 0.21.2", + "darling", "ident_case", "prettyplease", "proc-macro2", "quote", "rustversion", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -557,10 +570,11 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.32" +version = "1.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e" +checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -574,30 +588,35 @@ checksum = "4f4c707c6a209cbe82d10abd08e1ea8995e9ea937d2550646e02798948992be0" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", - "num-traits", + "num-traits 0.2.19", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.0", ] [[package]] name = "clap" -version = "4.5.45" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", "clap_derive", @@ -605,9 +624,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstream", "anstyle", @@ -617,14 +636,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -645,7 +664,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -658,6 +677,23 @@ dependencies = [ "memchr", ] +[[package]] +name = "compression-codecs" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64" +dependencies = [ + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" + [[package]] name = "concolor" version = "0.1.1" @@ -715,6 +751,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "countmap" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ef2a403c4af585607826502480ab6e453f320c230ef67255eee21f0cc72c0a6" +dependencies = [ + "num-traits 0.1.43", +] + [[package]] name = "countme" version = "3.0.1" @@ -791,81 +836,47 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - -[[package]] -name = "darling" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570" -dependencies = [ - "darling_core 0.21.2", - "darling_macro 0.21.2", -] - -[[package]] -name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "syn 2.0.105", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.105", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "darling_macro" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core 0.21.2", + "darling_core", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "deadpool" -version = "0.10.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ - "async-trait", "deadpool-runtime", + "lazy_static", "num_cpus", "tokio", ] @@ -878,9 +889,9 @@ checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", "serde", @@ -904,7 +915,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "unicode-xid", ] @@ -926,14 +937,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "downcast-rs" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" [[package]] name = "dyn-clone" @@ -950,7 +961,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -974,6 +985,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "enum-ordinalize" version = "4.3.0" @@ -991,28 +1011,28 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "enumset" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee17054f550fd7400e1906e2f9356c7672643ed34008a9e8abe147ccd2d821" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d07902c93376f1e96c34abc4d507c0911df3816cef50b01f5a2ff3ad8c370d" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" dependencies = [ - "darling 0.20.11", + "darling", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -1023,12 +1043,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -1070,6 +1090,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -1126,9 +1152,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1219,7 +1245,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -1288,9 +1314,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.5+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1508,9 +1536,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "humantime-serde" @@ -1524,13 +1552,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -1538,11 +1567,29 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1710,9 +1757,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1731,9 +1778,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" dependencies = [ "equivalent", "hashbrown 0.15.5", @@ -1752,7 +1799,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "inotify-sys", "libc", ] @@ -1768,9 +1815,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.43.1" +version = "1.43.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371" +checksum = "46fdb647ebde000f43b5b53f773c30cf9b0cb4300453208713fa38b2c70935a0" dependencies = [ "console", "globset", @@ -1784,11 +1831,11 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "cfg-if", "libc", ] @@ -1817,7 +1864,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1843,9 +1890,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.3", "libc", @@ -1853,9 +1900,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" dependencies = [ "once_cell", "wasm-bindgen", @@ -1889,7 +1936,7 @@ dependencies = [ "idna", "itoa", "num-cmp", - "num-traits", + "num-traits 0.2.19", "once_cell", "percent-encoding", "referencing", @@ -1994,9 +2041,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -2016,9 +2063,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lru" @@ -2029,6 +2076,12 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz-str" version = "0.2.1" @@ -2073,9 +2126,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" dependencies = [ "libc", ] @@ -2202,7 +2255,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "fsevent-sys", "inotify", "kqueue", @@ -2240,7 +2293,7 @@ dependencies = [ "num-integer", "num-iter", "num-rational", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2250,7 +2303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2265,7 +2318,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2280,7 +2333,7 @@ version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2291,7 +2344,7 @@ checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2302,7 +2355,16 @@ checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.19", ] [[package]] @@ -2367,7 +2429,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "cfg-if", "foreign-types", "libc", @@ -2384,7 +2446,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2479,7 +2541,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2494,26 +2556,26 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" dependencies = [ "memchr", - "thiserror 2.0.14", + "thiserror 2.0.16", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" dependencies = [ "pest", "pest_generator", @@ -2521,22 +2583,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "pest_meta" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" dependencies = [ "pest", "sha2", @@ -2572,7 +2634,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2595,9 +2657,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -2619,12 +2681,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.36" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2638,9 +2700,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.97" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -2653,11 +2715,66 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "version_check", "yansi", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror 2.0.16", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.16", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.40" @@ -2738,7 +2855,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ - "num-traits", + "num-traits 0.2.19", "rand 0.8.5", ] @@ -2768,7 +2885,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", ] [[package]] @@ -2788,7 +2905,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2807,9 +2924,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -2819,9 +2936,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -2830,9 +2947,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "relative-path" @@ -2856,6 +2973,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", @@ -2863,6 +2981,8 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", "serde", "serde_json", @@ -2870,6 +2990,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -2877,7 +2998,9 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", + "webpki-roots", ] [[package]] @@ -2911,12 +3034,13 @@ dependencies = [ "paste", "pin-project-lite", "rand 0.9.2", + "reqwest", "rmcp-macros", "schemars", "serde", "serde_json", "sse-stream", - "thiserror 2.0.14", + "thiserror 2.0.16", "tokio", "tokio-stream", "tokio-util", @@ -2931,11 +3055,11 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1827cd98dab34cade0513243c6fe0351f0f0b2c9d6825460bcf45b42804bdda0" dependencies = [ - "darling 0.21.2", + "darling", "proc-macro2", "quote", "serde_json", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -2976,7 +3100,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.105", + "syn 2.0.106", "unicode-ident", ] @@ -3023,24 +3147,38 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.0", +] + +[[package]] +name = "rustls" +version = "0.23.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] @@ -3049,9 +3187,21 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-webpki" +version = "0.103.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -3075,11 +3225,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.0", ] [[package]] @@ -3106,7 +3256,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3131,7 +3281,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "core-foundation", "core-foundation-sys", "libc", @@ -3140,9 +3290,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -3171,7 +3321,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3182,14 +3332,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "indexmap", "itoa", @@ -3272,9 +3422,9 @@ dependencies = [ [[package]] name = "shape" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "362c1523018b16b65737aa0ea76a731edbcd399e273c0130ba829b148f89dbd2" +checksum = "914e2afe9130bf8acf52c5e20b4222f7d2e5eb8327e05fb668fe70aad4b3a896" dependencies = [ "apollo-compiler", "indexmap", @@ -3319,8 +3469,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", - "num-traits", - "thiserror 2.0.14", + "num-traits 0.2.19", + "thiserror 2.0.16", "time", ] @@ -3395,9 +3545,15 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -3411,9 +3567,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.105" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -3437,7 +3593,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3486,7 +3642,7 @@ dependencies = [ "tantivy-stacker", "tantivy-tokenizer-api", "tempfile", - "thiserror 2.0.14", + "thiserror 2.0.16", "time", "uuid", "winapi", @@ -3588,15 +3744,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.8", - "windows-sys 0.52.0", + "rustix 1.1.2", + "windows-sys 0.61.0", ] [[package]] @@ -3617,7 +3773,7 @@ checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3637,11 +3793,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.14" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.14", + "thiserror-impl 2.0.16", ] [[package]] @@ -3652,18 +3808,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.14" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3677,12 +3833,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" dependencies = [ "deranged", - "itoa", "libc", "num-conv", "num_threads", @@ -3694,15 +3849,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -3718,6 +3873,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.47.1" @@ -3746,7 +3916,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3759,6 +3929,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -3822,7 +4002,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "bytes", "futures-util", "http", @@ -3878,7 +4058,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -3963,7 +4143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -4011,9 +4191,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-segmentation" @@ -4047,9 +4227,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -4077,9 +4257,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -4149,44 +4329,54 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.5+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.0+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" dependencies = [ "cfg-if", "js-sys", @@ -4197,9 +4387,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4207,36 +4397,68 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4255,11 +4477,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.0", ] [[package]] @@ -4276,7 +4498,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -4289,7 +4511,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -4300,7 +4522,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -4309,13 +4531,19 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4324,7 +4552,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4363,6 +4591,15 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4400,7 +4637,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -4551,21 +4788,20 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] [[package]] name = "wiremock" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b8b99d4cdbf36b239a9532e31fe4fb8acc38d1897c1761e161550a7dc78e6a" +checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" dependencies = [ "assert-json-diff", - "async-trait", "base64", "deadpool", "futures", @@ -4583,13 +4819,10 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" [[package]] name = "writeable" @@ -4623,28 +4856,28 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -4664,7 +4897,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", "synstructure", ] @@ -4704,7 +4937,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.105", + "syn 2.0.106", ] [[package]] @@ -4727,9 +4960,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 69dbc455..e9bf3e0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "crates/apollo-mcp-server", "crates/apollo-mcp-registry", "crates/apollo-schema-index", + "crates/apollo-mcp-proxy", ] [workspace.package] @@ -17,6 +18,7 @@ version = "0.7.5" [workspace.dependencies] apollo-compiler = "1.27.0" apollo-federation = "2.1.3" +axum = "0.8.4" futures = { version = "0.3.31", features = ["thread-pool"] } insta = { version = "1.43.1", features = [ "json", @@ -29,6 +31,12 @@ reqwest = { version = "0.12.15", default-features = false, features = [ "json", "native-tls-vendored", ] } +rmcp = { version = "0.6", features = [ + "server", + "transport-io", + "transport-sse-server", + "transport-streamable-http-server", +] } rstest = "0.25.0" secrecy = { version = "0.10.3", features = ["serde"] } serde = { version = "1.0.219", features = ["derive"] } @@ -46,6 +54,7 @@ tokio = { version = "1.45.0", features = [ "time", ] } tokio-stream = "0.1" +tokio-util = "0.7.15" tracing = "0.1.41" tracing-core = "0.1.33" tracing-subscriber = { version = "0.3.19", features = ["json"] } diff --git a/crates/apollo-mcp-proxy/Cargo.toml b/crates/apollo-mcp-proxy/Cargo.toml new file mode 100644 index 00000000..ba0276d6 --- /dev/null +++ b/crates/apollo-mcp-proxy/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "apollo-mcp-proxy" +edition = "2024" +authors.workspace = true +version.workspace = true + +[dependencies] +axum.workspace = true +clap = { version = "4.5.40", features = ["derive"] } +tokio.workspace = true +tokio-util.workspace = true +rmcp = { workspace = true, features = [ + "client", + "reqwest", + "transport-streamable-http-client", +] } +tracing.workspace = true +tracing-appender = "0.2.3" +tracing-subscriber.workspace = true +serde_json = "1.0.140" +futures = "0.3.31" + +[lints] +workspace = true diff --git a/crates/apollo-mcp-proxy/src/client.rs b/crates/apollo-mcp-proxy/src/client.rs new file mode 100644 index 00000000..372824c2 --- /dev/null +++ b/crates/apollo-mcp-proxy/src/client.rs @@ -0,0 +1,52 @@ +use crate::non_blocking_stdio::NonBlockStdIo; +use crate::server::ProxyServer; +use rmcp::model::ProtocolVersion; +use rmcp::{ + ServiceExt, + model::{ClientCapabilities, ClientInfo, Implementation}, + transport::StreamableHttpClientTransport, +}; +use std::error::Error; +use tokio_util::sync::CancellationToken; +use tracing::{debug, error, info}; + +pub async fn start_proxy_client( + url: &str, + cancellation_token: CancellationToken, +) -> Result<(), Box> { + let transport = StreamableHttpClientTransport::from_uri(url); + let client_info = ClientInfo { + protocol_version: ProtocolVersion::LATEST, + capabilities: ClientCapabilities::default(), + client_info: Implementation { + name: "mcp remote rust client".to_string(), + title: None, + version: env!("CARGO_PKG_VERSION").to_string(), + icons: None, + website_url: None, + }, + }; + + let client = match client_info.serve(transport).await.inspect_err(|e| { + error!("[Proxy] client error: {:?}", e); + }) { + Ok(client) => client, + Err(e) => { + error!("[Proxy] client startup error: {:?}", e); + return Err(e.into()); + } + }; + + let server_info = client.peer_info(); + info!("[Proxy] Connected to server at {}", url); + debug!("{server_info:#?}"); + + let proxy_server = ProxyServer::new(client.peer().clone(), client.peer_info()); + + let stdio_transport = NonBlockStdIo::new(cancellation_token.child_token()); + let server = proxy_server + .serve_with_ct(stdio_transport, cancellation_token) + .await?; + server.waiting().await?; + Ok(()) +} diff --git a/crates/apollo-mcp-proxy/src/lib.rs b/crates/apollo-mcp-proxy/src/lib.rs new file mode 100644 index 00000000..9bac5b85 --- /dev/null +++ b/crates/apollo-mcp-proxy/src/lib.rs @@ -0,0 +1,3 @@ +pub mod client; +pub mod non_blocking_stdio; +pub mod server; diff --git a/crates/apollo-mcp-proxy/src/main.rs b/crates/apollo-mcp-proxy/src/main.rs new file mode 100644 index 00000000..b2af060c --- /dev/null +++ b/crates/apollo-mcp-proxy/src/main.rs @@ -0,0 +1,35 @@ +use apollo_mcp_proxy::client::start_proxy_client; +use clap::Parser; +use std::error::Error; +use tokio_util::sync::CancellationToken; +use tracing_appender::rolling::{RollingFileAppender, Rotation}; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; + +#[derive(Parser)] +struct Args { + #[arg(short, long)] + url: String, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Initialize logging + let file_appender = RollingFileAppender::builder() + .rotation(Rotation::NEVER) + .filename_prefix("apollo_mcp_proxy") + .filename_suffix("log") + .build("./logs")?; + + let (non_blocking_writer, _guard) = tracing_appender::non_blocking(file_appender); + + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer().with_writer(non_blocking_writer)) + .init(); + + let args = Args::parse(); + + let _ = start_proxy_client(&args.url, CancellationToken::new()).await; + + Ok(()) +} diff --git a/crates/apollo-mcp-proxy/src/non_blocking_stdio.rs b/crates/apollo-mcp-proxy/src/non_blocking_stdio.rs new file mode 100644 index 00000000..12619329 --- /dev/null +++ b/crates/apollo-mcp-proxy/src/non_blocking_stdio.rs @@ -0,0 +1,131 @@ +use rmcp::RoleServer; +use rmcp::service::{RxJsonRpcMessage, TxJsonRpcMessage}; +use rmcp::transport::Transport; +use std::io::{ErrorKind, Write}; +use tokio_util::sync::CancellationToken; +use tracing::{debug, error}; + +pub struct NonBlockStdIo { + tx_out: tokio::sync::mpsc::Sender>, + rx_in: tokio::sync::mpsc::Receiver>, +} + +impl NonBlockStdIo { + pub fn new(cancellation_token: CancellationToken) -> Self { + let (tx_in, rx_in) = tokio::sync::mpsc::channel(100); + let (tx_out, mut rx_out) = tokio::sync::mpsc::channel(100); + + let stdin_cancel_token = cancellation_token.clone(); + let stdout_cancel_token = cancellation_token.clone(); + + std::thread::spawn(move || { + for line_result in std::io::stdin().lines() { + let line = match line_result { + Ok(line) => line, + Err(e) => { + error!("[Proxy] Failed to read from stdin: {e:?}"); + stdin_cancel_token.cancel(); + break; + } + }; + + debug!("[Proxy] Stdin received: {line}"); + + let data = match serde_json::from_slice(line.as_bytes()) { + Ok(data) => data, + Err(e) => { + error!("[Proxy] Failed to deserialize json: {e:?}"); + stdin_cancel_token.cancel(); + break; + } + }; + + match tx_in.blocking_send(data) { + Ok(_) => {} + Err(e) => { + error!("[Proxy] Failed to send data: {e:?}"); + stdin_cancel_token.cancel(); + break; + } + } + } + }); + + std::thread::spawn(move || { + loop { + if let Some(data) = rx_out.blocking_recv() { + let data = serde_json::to_string(&data).unwrap_or_else(|e| { + error!("[Proxy] Couldn't serialize data: {e:?}"); + stdout_cancel_token.cancel(); + "".to_string() + }) + "\n"; + + match std::io::stdout().write_all(data.as_bytes()) { + Ok(_) => {} + Err(e) => { + error!("[Proxy] Failed to write data to stdout: {e:?}"); + stdout_cancel_token.cancel(); + break; + } + } + + match std::io::stdout().flush() { + Ok(_) => {} + Err(e) => { + error!("[Proxy] Failed to flush stdout: {e:?}"); + stdout_cancel_token.cancel(); + break; + } + } + } + } + }); + + Self { tx_out, rx_in } + } +} + +impl Transport for NonBlockStdIo { + type Error = tokio::io::Error; + + fn send( + &mut self, + item: TxJsonRpcMessage, + ) -> impl Future> + Send + 'static { + let tx = self.tx_out.clone(); + + async move { + debug!("Sending message to server: {item:?}"); + tx.send(item).await.map_err(|e| { + tokio::io::Error::new( + ErrorKind::BrokenPipe, + format!("NonBlockStdIo send error: {e:?}"), + ) + }) + } + } + + #[allow(clippy::manual_async_fn)] + fn receive(&mut self) -> impl Future>> + Send { + async move { + let data = self.rx_in.recv().await; + debug!("[NonBlockStdIo] Receiving {data:?}"); + data + } + } + + #[allow(clippy::manual_async_fn)] + fn close(&mut self) -> impl Future> + Send { + async move { + debug!("[NonBlockStdIo] Closing connection"); + self.rx_in.close(); + Ok(()) + } + } +} + +impl Drop for NonBlockStdIo { + fn drop(&mut self) { + debug!("[NonBlockStdIo] Dropping connection"); + } +} diff --git a/crates/apollo-mcp-proxy/src/server.rs b/crates/apollo-mcp-proxy/src/server.rs new file mode 100644 index 00000000..0f79f9c4 --- /dev/null +++ b/crates/apollo-mcp-proxy/src/server.rs @@ -0,0 +1,315 @@ +use rmcp::model::{ + CallToolRequestParam, CallToolResult, Content, GetPromptRequestParam, GetPromptResult, + Implementation, InitializeRequestParam, InitializeResult, ListPromptsResult, + ListResourceTemplatesResult, ListResourcesResult, ListToolsResult, PaginatedRequestParam, + ReadResourceRequestParam, ReadResourceResult, ServerInfo, +}; +use rmcp::service::{NotificationContext, RequestContext}; +use rmcp::{ErrorData, Peer, RoleClient, RoleServer, ServerHandler}; +use std::sync::Arc; +use tracing::{debug, error, info}; + +pub struct ProxyServer { + client: Arc>, + server_info: Arc, +} + +impl ProxyServer { + pub fn new(client_peer: Peer, peer_info: Option<&ServerInfo>) -> Self { + let mut server_info = ServerInfo::default(); + + if let Some(info) = peer_info { + server_info = ServerInfo { + protocol_version: info.protocol_version.clone(), + server_info: Implementation { + name: info.server_info.name.clone(), + title: None, + version: info.server_info.version.clone(), + icons: None, + website_url: None, + }, + instructions: info.instructions.clone(), + capabilities: info.capabilities.clone(), + }; + } + + debug!("[Proxy]server info: {:?}", server_info); + + Self { + client: Arc::new(client_peer), + server_info: Arc::new(server_info), + } + } +} + +impl ServerHandler for ProxyServer { + async fn initialize( + &self, + _request: InitializeRequestParam, + context: RequestContext, + ) -> Result { + if let Some(http_request_part) = context.extensions.get::() { + let initialize_headers = &http_request_part.headers; + let initialize_uri = &http_request_part.uri; + info!(?initialize_headers, %initialize_uri, "initialize from http server"); + } + + Ok(self.get_info()) + } + + async fn complete( + &self, + request: rmcp::model::CompleteRequestParam, + _context: RequestContext, + ) -> Result { + match self.client.complete(request).await { + Ok(result) => { + debug!("[Proxy] Proxying complete response"); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error completing: {:?}", err); + Err(ErrorData::internal_error( + format!("Error completing: {err}"), + None, + )) + } + } + } + + async fn get_prompt( + &self, + request: GetPromptRequestParam, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.prompts.is_none() { + error!("[Proxy] Server doesn't support the prompts capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the prompts capability".to_string(), + None, + )); + } + + match self.client.get_prompt(request).await { + Ok(result) => { + debug!("[Proxy] Proxying get_prompt response"); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error getting prompt: {:?}", err); + Err(ErrorData::internal_error( + format!("Error getting prompt: {err}"), + None, + )) + } + } + } + + async fn list_prompts( + &self, + request: Option, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.prompts.is_none() { + error!("[Proxy] Server doesn't support the prompts capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the prompts capability".to_string(), + None, + )); + } + + match self.client.list_prompts(request).await { + Ok(result) => { + debug!("[Proxy] Proxying list_prompts response"); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error listing prompts: {:?}", err); + Ok(ListPromptsResult::default()) + } + } + } + + async fn list_resources( + &self, + request: Option, + _: RequestContext, + ) -> Result { + if self.server_info.capabilities.resources.is_none() { + error!("[Proxy] Server doesn't support the resources capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the resources capability".to_string(), + None, + )); + } + + match self.client.list_resources(request).await { + Ok(list_resources_result) => { + debug!( + "Proxying list_resources response: {:?}", + list_resources_result + ); + Ok(list_resources_result) + } + Err(e) => { + error!("[Proxy] Error listing resources: {:?}", e); + Ok(ListResourcesResult::default()) + } + } + } + + async fn list_resource_templates( + &self, + request: Option, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.resources.is_none() { + error!("[Proxy] Server doesn't support the resources capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the resources capability".to_string(), + None, + )); + } + + match self.client.list_resource_templates(request).await { + Ok(list_resource_templates_result) => { + debug!( + "Proxying list_resource_templates response: {:?}", + list_resource_templates_result + ); + Ok(list_resource_templates_result) + } + Err(err) => { + error!("[Proxy] Error listing resource templates: {:?}", err); + Ok(ListResourceTemplatesResult::default()) + } + } + } + + async fn read_resource( + &self, + request: ReadResourceRequestParam, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.resources.is_none() { + error!("[Proxy] Server doesn't support the resources capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the resources capability".to_string(), + None, + )); + } + + match self + .client + .read_resource(ReadResourceRequestParam { + uri: request.uri.clone(), + }) + .await + { + Ok(result) => { + debug!( + "Proxying read_resource response for {}: {:?}", + request.uri, result + ); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error reading resource: {:?}", err); + Err(ErrorData::internal_error( + format!("Error reading resource: {err}"), + None, + )) + } + } + } + + async fn call_tool( + &self, + request: CallToolRequestParam, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.tools.is_none() { + error!("[Proxy] Server doesn't support the tools capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the tools capability".to_string(), + None, + )); + } + + match self.client.call_tool(request.clone()).await { + Ok(result) => { + debug!("[Proxy] Tool call succeeded: {:?}", result); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error calling tool: {:?}", err); + Ok(CallToolResult::error(vec![Content::text(format!( + "Error: {err}" + ))])) + } + } + } + + async fn list_tools( + &self, + request: Option, + _context: RequestContext, + ) -> Result { + if self.server_info.capabilities.tools.is_none() { + error!("[Proxy] Server doesn't support the tools capability"); + return Err(ErrorData::internal_error( + "Server doesn't support the tools capability".to_string(), + None, + )); + } + + match self.client.list_tools(request).await { + Ok(result) => { + debug!( + "Proxying list_tools response with {} tools: {:?}", + result.tools.len(), + result + ); + Ok(result) + } + Err(err) => { + error!("[Proxy] Error listing tools: {:?}", err); + Ok(ListToolsResult::default()) + } + } + } + + async fn on_cancelled( + &self, + notification: rmcp::model::CancelledNotificationParam, + _context: NotificationContext, + ) { + match self.client.notify_cancelled(notification).await { + Ok(_) => { + debug!("[Proxy] Proxying cancelled notification"); + } + Err(err) => { + error!("[Proxy] Error notifying cancelled: {:?}", err); + } + } + } + + async fn on_progress( + &self, + notification: rmcp::model::ProgressNotificationParam, + _context: NotificationContext, + ) { + match self.client.notify_progress(notification).await { + Ok(_) => { + debug!("[Proxy] Proxying progress notification"); + } + Err(err) => { + error!("[Proxy] Error notifying progress: {:?}", err); + } + } + } + + fn get_info(&self) -> ServerInfo { + self.server_info.as_ref().clone() + } +} diff --git a/crates/apollo-mcp-server/Cargo.toml b/crates/apollo-mcp-server/Cargo.toml index 3fe245b7..b618e527 100644 --- a/crates/apollo-mcp-server/Cargo.toml +++ b/crates/apollo-mcp-server/Cargo.toml @@ -15,8 +15,9 @@ apollo-compiler.workspace = true apollo-federation.workspace = true apollo-mcp-registry = { path = "../apollo-mcp-registry" } apollo-schema-index = { path = "../apollo-schema-index" } -axum = "0.8.4" axum-extra = { version = "0.10.1", features = ["typed-header"] } +apollo-mcp-proxy = { path = "../apollo-mcp-proxy" } +axum.workspace = true bon = "3.6.3" clap = { version = "4.5.36", features = ["derive", "env"] } figment = { version = "0.10.19", features = ["env", "yaml"] } @@ -30,21 +31,16 @@ jwks = "0.4.0" lz-str = "0.2.1" regex = "1.11.1" reqwest.workspace = true -rmcp = { version = "0.6", features = [ - "server", - "transport-io", - "transport-sse-server", - "transport-streamable-http-server", -] } +rmcp.workspace = true schemars = { version = "1.0.1", features = ["url2"] } serde.workspace = true serde_json.workspace = true thiserror.workspace = true tokio.workspace = true +tokio-util.workspace = true tracing.workspace = true tracing-appender = "0.2.3" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } -tokio-util = "0.7.15" tower-http = { version = "0.6.6", features = ["cors"] } url.workspace = true diff --git a/crates/apollo-mcp-server/src/errors.rs b/crates/apollo-mcp-server/src/errors.rs index caaa7f53..d5782df3 100644 --- a/crates/apollo-mcp-server/src/errors.rs +++ b/crates/apollo-mcp-server/src/errors.rs @@ -100,6 +100,9 @@ pub enum ServerError { #[error("Failed to index schema: {0}")] Indexing(#[from] IndexingError), + + #[error("Proxy options used with transport auth currently not supported")] + ProxyAuthNotSupported, } /// An MCP tool error diff --git a/crates/apollo-mcp-server/src/main.rs b/crates/apollo-mcp-server/src/main.rs index 3f3d8738..4fcb18bb 100644 --- a/crates/apollo-mcp-server/src/main.rs +++ b/crates/apollo-mcp-server/src/main.rs @@ -1,17 +1,19 @@ -use std::path::PathBuf; - +use apollo_mcp_proxy::client::start_proxy_client; use apollo_mcp_registry::platform_api::operation_collections::collection_poller::CollectionSource; use apollo_mcp_registry::uplink::persisted_queries::ManifestSource; use apollo_mcp_registry::uplink::schema::SchemaSource; use apollo_mcp_server::custom_scalar_map::CustomScalarMap; use apollo_mcp_server::errors::ServerError; use apollo_mcp_server::operations::OperationSource; -use apollo_mcp_server::server::Server; +use apollo_mcp_server::server::{Server, Transport}; use clap::Parser; use clap::builder::Styles; use clap::builder::styling::{AnsiColor, Effects}; use runtime::IdOrDefault; use runtime::logging::Logging; +use std::path::PathBuf; +use tokio::signal; +use tokio_util::sync::CancellationToken; use tracing::{info, warn}; mod runtime; @@ -111,8 +113,8 @@ async fn main() -> anyhow::Result<()> { let transport = config.transport.clone(); - Ok(Server::builder() - .transport(config.transport) + let mcp_server = Server::builder() + .transport(config.transport.clone()) .schema_source(schema_source) .operation_source(operation_source) .endpoint(config.endpoint.into_inner()) @@ -146,6 +148,36 @@ async fn main() -> anyhow::Result<()> { .index_memory_bytes(config.introspection.search.index_memory_bytes) .health_check(config.health_check) .build() - .start() - .await?) + .start(); + + match config.transport { + Transport::StreamableHttp { + address, + port, + auth, + } => { + if config.proxy.enabled { + if auth.is_some() { + anyhow::bail!(ServerError::ProxyAuthNotSupported) + } + + let url = config.proxy.url(&address, &port); + let cancellation_token: CancellationToken = CancellationToken::new(); + + tokio::select! { + biased; + _ = signal::ctrl_c() => { cancellation_token.cancel(); } + _ = mcp_server => {} + _ = start_proxy_client(url.as_str(), cancellation_token.child_token()) => {} + } + } else { + mcp_server.await?; + } + } + _ => { + mcp_server.await?; + } + } + + Ok(()) } diff --git a/crates/apollo-mcp-server/src/runtime.rs b/crates/apollo-mcp-server/src/runtime.rs index bc63f7af..26e7d496 100644 --- a/crates/apollo-mcp-server/src/runtime.rs +++ b/crates/apollo-mcp-server/src/runtime.rs @@ -10,11 +10,10 @@ mod introspection; pub mod logging; mod operation_source; mod overrides; +mod proxy; mod schema_source; mod schemas; -use std::path::Path; - pub use config::Config; use figment::{ Figment, @@ -22,6 +21,7 @@ use figment::{ }; pub use operation_source::{IdOrDefault, OperationSource}; pub use schema_source::SchemaSource; +use std::path::Path; /// Separator to use when drilling down into nested options in the env figment const ENV_NESTED_SEPARATOR: &str = "__"; @@ -165,7 +165,9 @@ mod test { }, ), graphos: GraphOSConfig { - apollo_key: None, + apollo_key: Some( + SecretBox([REDACTED]), + ), apollo_graph_ref: None, apollo_registry_url: None, apollo_uplink_endpoints: [ @@ -251,6 +253,10 @@ mod test { }, schema: Uplink, transport: Stdio, + proxy: ProxyConfig { + enabled: false, + url: None, + }, } "#); Ok(()) diff --git a/crates/apollo-mcp-server/src/runtime/config.rs b/crates/apollo-mcp-server/src/runtime/config.rs index 8f64f518..fe6ca5b7 100644 --- a/crates/apollo-mcp-server/src/runtime/config.rs +++ b/crates/apollo-mcp-server/src/runtime/config.rs @@ -8,7 +8,7 @@ use url::Url; use super::{ OperationSource, SchemaSource, endpoint::Endpoint, graphos::GraphOSConfig, - introspection::Introspection, logging::Logging, overrides::Overrides, + introspection::Introspection, logging::Logging, overrides::Overrides, proxy::ProxyConfig, }; /// Configuration for the MCP server @@ -51,6 +51,10 @@ pub struct Config { /// The type of server transport to use pub transport: Transport, + + /// The optional proxy client options + #[serde(default)] + pub proxy: ProxyConfig, } mod parsers { diff --git a/crates/apollo-mcp-server/src/runtime/proxy.rs b/crates/apollo-mcp-server/src/runtime/proxy.rs new file mode 100644 index 00000000..14524b4b --- /dev/null +++ b/crates/apollo-mcp-server/src/runtime/proxy.rs @@ -0,0 +1,32 @@ +use schemars::JsonSchema; +use serde::Deserialize; +use std::net::IpAddr; +use url::Url; + +/// Proxy client related config options +/// Note: only supported for Streamable HTTP +#[derive(Debug, Deserialize, JsonSchema, Default)] +#[serde(default)] +pub struct ProxyConfig { + /// Flag indicating whether the proxy client is enabled or not + #[serde(default)] + pub enabled: bool, + + /// Proxy url address + /// [default: http://:/mcp] + #[serde(default)] + pub url: Option, +} + +impl ProxyConfig { + pub(crate) fn url(&self, transport_address: &IpAddr, transport_port: &u16) -> Url { + match &self.url { + Some(proxy_url) => proxy_url.clone(), + None => { + let address = format!("http://{transport_address}:{transport_port}/mcp"); + #[allow(clippy::unwrap_used)] + Url::parse(address.as_str()).unwrap() + } + } + } +} diff --git a/crates/apollo-mcp-server/src/server/states/starting.rs b/crates/apollo-mcp-server/src/server/states/starting.rs index 4ef0dac4..18ae064f 100644 --- a/crates/apollo-mcp-server/src/server/states/starting.rs +++ b/crates/apollo-mcp-server/src/server/states/starting.rs @@ -168,8 +168,8 @@ impl Starting { auth, address, port, + .. } => { - info!(port = ?port, address = ?address, "Starting MCP server in Streamable HTTP mode"); let running = running.clone(); let listen_address = SocketAddr::new(address, port); let service = StreamableHttpService::new(