diff --git a/Cargo.lock b/Cargo.lock
index 66a51f0..bd71ede 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,6 +17,48 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
+[[package]]
+name = "assert-json-diff"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "async-channel"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
+
[[package]]
name = "async-trait"
version = "0.1.88"
@@ -28,17 +70,122 @@ dependencies = [
"syn",
]
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+[[package]]
+name = "aws-lc-rs"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7"
+dependencies = [
+ "aws-lc-sys",
+ "zeroize",
+]
+
+[[package]]
+name = "aws-lc-sys"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079"
+dependencies = [
+ "bindgen",
+ "cc",
+ "cmake",
+ "dunce",
+ "fs_extra",
+]
+
+[[package]]
+name = "axum"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
+dependencies = [
+ "axum-core",
+ "bytes",
+ "form_urlencoded",
+ "futures-util",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.6.0",
+ "hyper-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "rustversion",
+ "sync_wrapper",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-server"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab"
+dependencies = [
+ "arc-swap",
+ "bytes",
+ "fs-err",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "hyper 1.6.0",
+ "hyper-util",
+ "pin-project-lite",
+ "rustls",
+ "rustls-pemfile",
+ "rustls-pki-types",
+ "tokio",
+ "tokio-rustls",
+ "tower-service",
+]
+
[[package]]
name = "backtrace"
-version = "0.3.74"
+version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
@@ -46,7 +193,48 @@ dependencies = [
"miniz_oxide",
"object",
"rustc-demangle",
- "windows-targets",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[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"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "bindgen"
+version = "0.69.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "itertools",
+ "lazy_static",
+ "lazycell",
+ "log",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+ "which",
]
[[package]]
@@ -55,18 +243,64 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+[[package]]
+name = "bumpalo"
+version = "3.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
+
[[package]]
name = "bytes"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+[[package]]
+name = "cc"
+version = "1.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1"
+dependencies = [
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "cmake"
+version = "0.1.54"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "colored"
version = "3.0.0"
@@ -76,6 +310,171 @@ dependencies = [
"windows-sys 0.59.0",
]
+[[package]]
+name = "concurrent-queue"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "deadpool"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "421fe0f90f2ab22016f32a9881be5134fdd71c65298917084b0c7477cbc3856e"
+dependencies = [
+ "async-trait",
+ "deadpool-runtime",
+ "num_cpus",
+ "retain_mut",
+ "tokio",
+]
+
+[[package]]
+name = "deadpool-runtime"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b"
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[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 = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "errno"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fs-err"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f89bda4c2a21204059a977ed3bfe746677dfd137b83c339e702b0ac91d482aa"
+dependencies = [
+ "autocfg",
+ "tokio",
+]
+
+[[package]]
+name = "fs_extra"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
+
[[package]]
name = "futures"
version = "0.3.31"
@@ -124,6 +523,21 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+[[package]]
+name = "futures-lite"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
+dependencies = [
+ "fastrand 1.9.0",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
[[package]]
name = "futures-macro"
version = "0.3.31"
@@ -147,6 +561,12 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+[[package]]
+name = "futures-timer"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
+
[[package]]
name = "futures-util"
version = "0.3.31"
@@ -166,391 +586,1949 @@ dependencies = [
]
[[package]]
-name = "gimli"
-version = "0.31.1"
+name = "getrandom"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-
-[[package]]
-name = "hello-world-mcp-server"
-version = "0.1.9"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
- "async-trait",
- "futures",
- "rust-mcp-schema",
- "rust-mcp-sdk",
- "serde",
- "serde_json",
- "tokio",
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
-name = "hello-world-mcp-server-core"
-version = "0.1.9"
+name = "getrandom"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
- "async-trait",
- "futures",
- "rust-mcp-schema",
- "rust-mcp-sdk",
- "serde",
- "serde_json",
- "tokio",
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
-name = "itoa"
-version = "1.0.15"
+name = "getrandom"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi 0.14.2+wasi-0.2.4",
+]
[[package]]
-name = "libc"
-version = "0.2.171"
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "glob"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
+
+[[package]]
+name = "h2"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http 0.2.12",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "h2"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "http 1.3.1",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
+
+[[package]]
+name = "hello-world-mcp-server"
+version = "0.1.9"
+dependencies = [
+ "async-trait",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "hello-world-mcp-server-core"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "tokio",
+]
+
+[[package]]
+name = "hello-world-server-core-sse"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "hello-world-server-sse"
+version = "0.1.9"
+dependencies = [
+ "async-trait",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "home"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http 0.2.12",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+dependencies = [
+ "bytes",
+ "http 1.3.1",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-types"
+version = "2.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad"
+dependencies = [
+ "anyhow",
+ "async-channel",
+ "base64 0.13.1",
+ "futures-lite",
+ "http 0.2.12",
+ "infer",
+ "pin-project-lite",
+ "rand",
+ "serde",
+ "serde_json",
+ "serde_qs",
+ "serde_urlencoded",
+ "url",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2 0.3.26",
+ "http 0.2.12",
+ "http-body 0.4.6",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "h2 0.4.10",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+ "want",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.27.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
+dependencies = [
+ "futures-util",
+ "http 1.3.1",
+ "hyper 1.6.0",
+ "hyper-util",
+ "rustls",
+ "rustls-pki-types",
+ "tokio",
+ "tokio-rustls",
+ "tower-service",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
+dependencies = [
+ "bytes",
+ "http-body-util",
+ "hyper 1.6.0",
+ "hyper-util",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "hyper 1.6.0",
+ "libc",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "icu_collections"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
+
+[[package]]
+name = "icu_properties"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "potential_utf",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04"
+
+[[package]]
+name = "icu_provider"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "idna"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "infer"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac"
+
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "jobserver"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
+dependencies = [
+ "getrandom 0.3.3",
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.172"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
+
+[[package]]
+name = "libloading"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
+dependencies = [
+ "cfg-if",
+ "windows-targets 0.53.0",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
+[[package]]
+name = "litemap"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
+[[package]]
+name = "matchit"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "mio"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+dependencies = [
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "openssl"
+version = "0.10.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "parking"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "potential_utf"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
+dependencies = [
+ "zerovec",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "reqwest"
+version = "0.12.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2 0.4.10",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.6.0",
+ "hyper-rustls",
+ "hyper-tls",
+ "hyper-util",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
+ "tokio",
+ "tokio-native-tls",
+ "tokio-util",
+ "tower",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
+ "windows-registry",
+]
+
+[[package]]
+name = "retain_mut"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0"
+
+[[package]]
+name = "ring"
+version = "0.17.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "getrandom 0.2.16",
+ "libc",
+ "untrusted",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rust-mcp-macros"
+version = "0.2.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rust-mcp-schema",
+ "serde",
+ "serde_json",
+ "syn",
+]
+
+[[package]]
+name = "rust-mcp-schema"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "868d31d0ae0376ba45786eac9058771da06839e83bb961ac7e5997ab3910f086"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "rust-mcp-sdk"
+version = "0.2.4"
+dependencies = [
+ "async-trait",
+ "axum",
+ "axum-server",
+ "futures",
+ "hyper 1.6.0",
+ "rust-mcp-macros",
+ "rust-mcp-schema",
+ "rust-mcp-transport",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "tracing-subscriber",
+ "uuid",
+]
+
+[[package]]
+name = "rust-mcp-transport"
+version = "0.2.1"
+dependencies = [
+ "async-trait",
+ "axum",
+ "bytes",
+ "futures",
+ "reqwest",
+ "rust-mcp-schema",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "uuid",
+ "wiremock",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustix"
+version = "0.38.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.15",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "rustix"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.9.4",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.23.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
+dependencies = [
+ "aws-lc-rs",
+ "once_cell",
+ "rustls-pki-types",
+ "rustls-webpki",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
+dependencies = [
+ "rustls-pki-types",
+]
+
+[[package]]
+name = "rustls-pki-types"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
+dependencies = [
+ "zeroize",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.103.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
+dependencies = [
+ "aws-lc-rs",
+ "ring",
+ "rustls-pki-types",
+ "untrusted",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "schannel"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "security-framework"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
+dependencies = [
+ "itoa",
+ "serde",
+]
+
+[[package]]
+name = "serde_qs"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6"
+dependencies = [
+ "percent-encoding",
+ "serde",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "simple-mcp-client"
+version = "0.1.9"
+dependencies = [
+ "async-trait",
+ "colored",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+]
+
+[[package]]
+name = "simple-mcp-client-core"
+version = "0.1.9"
+dependencies = [
+ "async-trait",
+ "colored",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+]
+
+[[package]]
+name = "simple-mcp-client-core-sse"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "colored",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
[[package]]
-name = "lock_api"
-version = "0.4.12"
+name = "simple-mcp-client-sse"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "colored",
+ "futures",
+ "rust-mcp-schema",
+ "rust-mcp-sdk",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.12",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
- "scopeguard",
]
[[package]]
-name = "memchr"
-version = "2.7.4"
+name = "smallvec"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
[[package]]
-name = "miniz_oxide"
-version = "0.8.7"
+name = "socket2"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
dependencies = [
- "adler2",
+ "libc",
+ "windows-sys 0.52.0",
]
[[package]]
-name = "mio"
-version = "1.0.3"
+name = "stable_deref_trait"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "2.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "system-configuration"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
+ "core-foundation-sys",
"libc",
- "wasi",
- "windows-sys 0.52.0",
]
[[package]]
-name = "object"
-version = "0.36.7"
+name = "tempfile"
+version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
- "memchr",
+ "fastrand 2.3.0",
+ "getrandom 0.3.3",
+ "once_cell",
+ "rustix 1.0.7",
+ "windows-sys 0.59.0",
]
[[package]]
-name = "parking_lot"
-version = "0.12.3"
+name = "thiserror"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
- "lock_api",
- "parking_lot_core",
+ "thiserror-impl 1.0.69",
]
[[package]]
-name = "parking_lot_core"
-version = "0.9.10"
+name = "thiserror"
+version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+dependencies = [
+ "thiserror-impl 2.0.12",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "tokio"
+version = "1.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
+dependencies = [
+ "backtrace",
+ "bytes",
"libc",
- "redox_syscall",
- "smallvec",
- "windows-targets",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.52.0",
]
[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
+name = "tokio-macros"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
-name = "pin-utils"
-version = "0.1.0"
+name = "tokio-native-tls"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
[[package]]
-name = "proc-macro2"
-version = "1.0.94"
+name = "tokio-rustls"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
- "unicode-ident",
+ "rustls",
+ "tokio",
]
[[package]]
-name = "quote"
-version = "1.0.40"
+name = "tokio-stream"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
- "proc-macro2",
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
]
[[package]]
-name = "redox_syscall"
-version = "0.5.11"
+name = "tokio-util"
+version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
+checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
dependencies = [
- "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
]
[[package]]
-name = "rust-mcp-macros"
-version = "0.2.1"
+name = "tower"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
- "rust-mcp-schema",
- "serde",
- "serde_json",
"syn",
]
[[package]]
-name = "rust-mcp-schema"
-version = "0.4.0"
+name = "tracing-core"
+version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "868d31d0ae0376ba45786eac9058771da06839e83bb961ac7e5997ab3910f086"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
- "serde",
- "serde_json",
+ "once_cell",
+ "valuable",
]
[[package]]
-name = "rust-mcp-sdk"
-version = "0.2.4"
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
- "async-trait",
- "futures",
- "rust-mcp-macros",
- "rust-mcp-schema",
- "rust-mcp-transport",
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "untrusted"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
+[[package]]
+name = "url"
+version = "2.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
"serde",
- "serde_json",
- "thiserror",
- "tokio",
]
[[package]]
-name = "rust-mcp-transport"
-version = "0.2.1"
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "uuid"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
+dependencies = [
+ "getrandom 0.3.3",
+]
+
+[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "waker-fn"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
- "async-trait",
- "futures",
- "rust-mcp-schema",
- "serde",
- "serde_json",
- "thiserror",
- "tokio",
+ "try-lock",
]
[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
-name = "ryu"
-version = "1.0.20"
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
-name = "scopeguard"
-version = "1.2.0"
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
[[package]]
-name = "serde"
-version = "1.0.219"
+name = "wasm-bindgen"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
- "serde_derive",
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
]
[[package]]
-name = "serde_derive"
-version = "1.0.219"
+name = "wasm-bindgen-backend"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
+ "bumpalo",
+ "log",
"proc-macro2",
"quote",
"syn",
+ "wasm-bindgen-shared",
]
[[package]]
-name = "serde_json"
-version = "1.0.140"
+name = "wasm-bindgen-futures"
+version = "0.4.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
+ "cfg-if",
+ "js-sys",
+ "once_cell",
+ "wasm-bindgen",
+ "web-sys",
]
[[package]]
-name = "signal-hook-registry"
-version = "1.4.2"
+name = "wasm-bindgen-macro"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
- "libc",
+ "quote",
+ "wasm-bindgen-macro-support",
]
[[package]]
-name = "simple-mcp-client"
-version = "0.1.9"
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
- "async-trait",
- "colored",
- "futures",
- "rust-mcp-schema",
- "rust-mcp-sdk",
- "serde",
- "serde_json",
- "thiserror",
- "tokio",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
]
[[package]]
-name = "simple-mcp-client-core"
-version = "0.1.9"
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
- "async-trait",
- "colored",
- "futures",
- "rust-mcp-schema",
- "rust-mcp-sdk",
- "serde",
- "serde_json",
- "thiserror",
- "tokio",
+ "unicode-ident",
]
[[package]]
-name = "slab"
-version = "0.4.9"
+name = "wasm-streams"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
dependencies = [
- "autocfg",
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
]
[[package]]
-name = "smallvec"
-version = "1.15.0"
+name = "web-sys"
+version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
+checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
[[package]]
-name = "socket2"
-version = "0.5.9"
+name = "which"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
+checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
- "libc",
- "windows-sys 0.52.0",
+ "either",
+ "home",
+ "once_cell",
+ "rustix 0.38.44",
]
[[package]]
-name = "syn"
-version = "2.0.100"
+name = "winapi"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
]
[[package]]
-name = "thiserror"
-version = "2.0.12"
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
-dependencies = [
- "thiserror-impl",
-]
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
-name = "thiserror-impl"
-version = "2.0.12"
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "tokio"
-version = "1.44.2"
+name = "windows-link"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
-dependencies = [
- "backtrace",
- "bytes",
- "libc",
- "mio",
- "parking_lot",
- "pin-project-lite",
- "signal-hook-registry",
- "socket2",
- "tokio-macros",
- "windows-sys 0.52.0",
-]
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
-name = "tokio-macros"
-version = "2.5.0"
+name = "windows-registry"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "windows-result",
+ "windows-strings",
+ "windows-targets 0.53.0",
]
[[package]]
-name = "unicode-ident"
-version = "1.0.18"
+name = "windows-result"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d"
+dependencies = [
+ "windows-link",
+]
[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
+name = "windows-strings"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+dependencies = [
+ "windows-link",
+]
[[package]]
name = "windows-sys"
@@ -558,7 +2536,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -567,7 +2545,7 @@ version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -576,14 +2554,30 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
]
[[package]]
@@ -592,44 +2586,233 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
+[[package]]
+name = "wiremock"
+version = "0.5.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13a3a53eaf34f390dd30d7b1b078287dd05df2aa2e21a589ccb80f5c7253c2e9"
+dependencies = [
+ "assert-json-diff",
+ "async-trait",
+ "base64 0.21.7",
+ "deadpool",
+ "futures",
+ "futures-timer",
+ "http-types",
+ "hyper 0.14.32",
+ "log",
+ "once_cell",
+ "regex",
+ "serde",
+ "serde_json",
+ "tokio",
+]
+
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "writeable"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
+
+[[package]]
+name = "yoke"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerotrie"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 09eb82f..d19b489 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,10 @@ members = [
"examples/simple-mcp-client-core",
"examples/hello-world-mcp-server",
"examples/hello-world-mcp-server-core",
+ "examples/hello-world-server-sse",
+ "examples/hello-world-server-core-sse",
+ "examples/simple-mcp-client-sse",
+ "examples/simple-mcp-client-core-sse",
]
[workspace.dependencies]
@@ -26,6 +30,7 @@ async-trait = { version = "0.1" }
strum = { version = "0.27", features = ["derive"] }
thiserror = { version = "2.0" }
tokio-stream = { version = "0.1" }
+uuid = { version = "1" }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = [
"env-filter",
@@ -33,6 +38,12 @@ tracing-subscriber = { version = "0.3", features = [
"fmt",
] }
+axum = "0.8"
+rustls = "0.23"
+tokio-rustls = "0.26"
+axum-server = { version = "0.7" }
+reqwest = "0.12"
+bytes = "1.10.1"
# [workspace.dependencies.windows]
diff --git a/Makefile.toml b/Makefile.toml
index f8b65af..8d11b2d 100644
--- a/Makefile.toml
+++ b/Makefile.toml
@@ -8,7 +8,7 @@ args = ["fmt", "--all", "--", "--check"]
[tasks.clippy]
command = "cargo"
-args = ["clippy"]
+args = ["clippy", "--workspace", "--all-targets", "--all-features"]
[tasks.test]
install_crate = "nextest"
diff --git a/README.md b/README.md
index 3034fdf..b79bd66 100644
--- a/README.md
+++ b/README.md
@@ -11,26 +11,44 @@
[
](examples/hello-world-mcp-server)
-A high-performance, asynchronous toolkit for building MCP servers and clients.
+A high-performance, asynchronous toolkit for building MCP servers and clients.
Focus on your app's logic while **rust-mcp-sdk** takes care of the rest!
-**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
+**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
Leveraging the [rust-mcp-schema](https://github.com/rust-mcp-stack/rust-mcp-schema) crate simplifies the process of building robust and reliable MCP servers and clients, ensuring consistency and minimizing errors in data handling and message processing.
-**⚠️WARNING**: This project only supports Standard Input/Output (stdio) transport at this time, with support for SSE (Server-Sent Events) transport still in progress and not yet available. Project is currently under development and should be used at your own risk.
+This project currently supports following transports:
+- **stdio** (Standard Input/Output)
+- **sse** (Server-Sent Events).
-## Projects using `rust-mcp-sdk`
-Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
-| Icon | Name | Description | Link |
-|------|------|-------------|------|
-|
| [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
-|
| [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
+🚀 The **rust-mcp-sdk** includes a lightweight [Axum](https://github.com/tokio-rs/axum) based server that handles all core functionality seamlessly. Switching between `stdio` and `sse` is straightforward, requiring minimal code changes. The server is designed to efficiently handle multiple concurrent client connections and offers built-in support for SSL.
+
+**⚠️** **Streamable HTTP** transport and authentication still in progress and not yet available. Project is currently under development and should be used at your own risk.
+
+## Table of Contents
+- [Usage Examples](#usage-examples)
+ - [MCP Server (stdio)](#mcp-server-stdio)
+ - [MCP Server (sse)](#mcp-server-sse)
+ - [MCP Client (stdio)](#mcp-client-stdio)
+ - [MCP Client (sse)](#mcp-client-sse)
+- [Cargo features](#cargo-features)
+ - [Available Features](#available-features)
+ - [Default Features](#default-features)
+ - [Using Only the server Features](#using-only-the-server-features)
+ - [Using Only the client Features](#using-only-the-client-features)
+- [Choosing Between Standard and Core Handlers traits](#choosing-between-standard-and-core-handlers-traits)
+ - [Choosing Between **ServerHandler** and **ServerHandlerCore**](#choosing-between-serverhandler-and-serverhandlercore)
+ - [Choosing Between **ClientHandler** and **ClientHandlerCore**](#choosing-between-clienthandler-and-clienthandlercore)
+- [Projects using Rust MCP SDK](#projects-using-rust-mcp-sdk)
+- [Contributing](#contributing)
+- [Development](#development)
+- [License](#license)
## Usage Examples
-### MCP Server
+### MCP Server (stdio)
Create a MCP server with a `tool` that will print a `Hello World!` message:
@@ -70,7 +88,55 @@ async fn main() -> SdkResult<()> {
}
```
-The implementation of `MyServerHandler` could be as simple as the following:
+See hello-world-mcp-server example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
+
+
+
+### MCP Server (sse)
+
+Creating an MCP server in `rust-mcp-sdk` with the `sse` transport allows multiple clients to connect simultaneously with no additional setup.
+Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and transform options.
+
+```rust
+
+// STEP 1: Define server details and capabilities
+let server_details = InitializeResult {
+ // server name and version
+ server_info: Implementation {
+ name: "Hello World MCP Server".to_string(),
+ version: "0.1.0".to_string(),
+ },
+ capabilities: ServerCapabilities {
+ // indicates that server support mcp tools
+ tools: Some(ServerCapabilitiesTools { list_changed: None }),
+ ..Default::default() // Using default values for other fields
+ },
+ meta: None,
+ instructions: Some("server instructions...".to_string()),
+ protocol_version: LATEST_PROTOCOL_VERSION.to_string(),
+};
+
+// STEP 2: instantiate our custom handler for handling MCP messages
+let handler = MyServerHandler {};
+
+// STEP 3: instantiate HyperServer, providing `server_details` , `handler` and HyperServerOptions
+let server = hyper_server::create_server(
+ server_details,
+ handler,
+ HyperServerOptions {
+ host: "127.0.0.1".to_string(),
+ ..Default::default()
+ },
+);
+
+// STEP 4: Start the server
+server.start().await?;
+
+Ok(())
+```
+
+
+The implementation of `MyServerHandler` is the same regardless of the transport used and could be as simple as the following:
```rust
@@ -116,13 +182,13 @@ impl ServerHandler for MyServerHandler {
👉 For a more detailed example of a [Hello World MCP](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server) Server that supports multiple tools and provides more type-safe handling of `CallToolRequest`, check out: **[examples/hello-world-mcp-server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server)**
-See hello-world-mcp-server example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
+See hello-world-server-sse example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
-
+
---
-### MCP Client
+### MCP Client (stdio)
Create an MCP client that starts the [@modelcontextprotocol/server-everything](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) server, displays the server's name, version, and list of tools, then uses the add tool provided by the server to sum 120 and 28, printing the result.
@@ -203,23 +269,38 @@ Here is the output :
> your results may vary slightly depending on the version of the MCP Server in use when you run it.
+### MCP Client (sse)
+Creating an MCP client using the `rust-mcp-sdk` with the SSE transport is almost identical, with one exception at `step 3`. Instead of creating a `StdioTransport`, you simply create a `ClientSseTransport`. The rest of the code remains the same:
+
+```diff
+- let transport = StdioTransport::create_with_server_launch(
+- "npx",
+- vec![ "-y".to_string(), "@modelcontextprotocol/server-everything".to_string()],
+- None, TransportOptions::default()
+-)?;
++ let transport = ClientSseTransport::new(MCP_SERVER_URL, ClientSseTransportOptions::default())?;
+```
+
+
## Getting Started
If you are looking for a step-by-step tutorial on how to get started with `rust-mcp-sdk` , please see : [Getting Started MCP Server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/doc/getting-started-mcp-server.md)
-## Features
+## Cargo Features
-The `rust-mcp-sdk` crate provides three optional features: `server` , `client` and `macros`. By default, all features are enabled for maximum functionality. You can customize which features to include based on your project's needs.
+The `rust-mcp-sdk` crate provides several features that can be enabled or disabled. By default, all features are enabled to ensure maximum functionality, but you can customize which ones to include based on your project's requirements.
### Available Features
-- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP services.
+- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP servers.
- `client`: Activates MCP client capabilities, offering modules and APIs for client development and communicating with MCP servers.
+- `hyper-server`: This feature enables the **sse** transport for MCP servers, supporting multiple simultaneous client connections out of the box.
+- `ssl`: This feature enables TLS/SSL support for the **sse** transport when used with the `hyper-server`.
- `macros`: Provides procedural macros for simplifying the creation and manipulation of MCP Tool structures.
-### Default Behavior
+### Default Features
-All features (server, client, and macros) are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
+All features are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
@@ -230,7 +311,7 @@ rust-mcp-sdk = "0.2.0"
-### Using Only the server Feature
+### Using Only the server Features
If you only need the MCP Server functionality, you can disable the default features and explicitly enable the server feature. Add the following to your Cargo.toml:
@@ -240,10 +321,11 @@ If you only need the MCP Server functionality, you can disable the default featu
[dependencies]
rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["server","macros"] }
```
+Optionally add `hyper-server` for **sse** transport, and `ssl` feature for tls/ssl support of the `hyper-server`
-### Using Only the client Feature
+### Using Only the client Features
If you only need the MCP Client functionality, you can disable the default features and explicitly enable the client feature. Add the following to your Cargo.toml:
@@ -256,28 +338,59 @@ rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["clien
-### Choosing Between `mcp_server_handler` and `mcp_server_handler_core`
+## Choosing Between Standard and Core Handlers traits
+Learn when to use the `mcp_*_handler` traits versus the lower-level `mcp_*_handler_core` traits for both server and client implementations. This section helps you decide based on your project's need for simplicity versus fine-grained control.
+
+### Choosing Between `ServerHandler` and `ServerHandlerCore`
[rust-mcp-sdk](https://github.com/rust-mcp-stack/rust-mcp-sdk) provides two type of handler traits that you can chose from:
-- **mcp_server_handler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
+- **ServerHandler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
Refer to [examples/hello-world-mcp-server/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server/src/handler.rs) for an example.
-- **mcp_server_handler_core**: If you need more control over MCP messages, consider using `mcp_server_handler_core`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
+- **ServerHandlerCore**: If you need more control over MCP messages, consider using `ServerHandlerCore`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
Refer to [examples/hello-world-mcp-server-core/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server-core/src/handler.rs) for an example.
---
-**👉 Note:** Depending on your choice between `mcp_server_handler` and `mcp_server_handler_core`, you must use either `server_runtime::create_server()` or `server_runtime_core::create_server()` , respectively.
+**👉 Note:** Depending on whether you choose `ServerHandler` or `ServerHandlerCore`, you must use the `create_server()` function from the appropriate module:
+
+- For `ServerHandler`:
+ - Use `server_runtime::create_server()` for servers with stdio transport
+ - Use `hyper_server::create_server()` for servers with sse transport
+
+- For `ServerHandlerCore`:
+ - Use `server_runtime_core::create_server()` for servers with stdio transport
+ - Use `hyper_server_core::create_server()` for servers with sse transport
---
-### Choosing Between `mcp_client_handler` and `mcp_client_handler_core`
-The same principles outlined above apply to the client-side handlers, `mcp_client_handler` and `mcp_client_handler_core`.
-Use `client_runtime::create_client()` or `client_runtime_core::create_client()` , respectively.
+### Choosing Between `ClientHandler` and `ClientHandlerCore`
+
+The same principles outlined above apply to the client-side handlers, `ClientHandler` and `ClientHandlerCore`.
+
+- Use `client_runtime::create_client()` when working with `ClientHandler`
+
+- Use `client_runtime_core::create_client()` when working with `ClientHandlerCore`
+
+Both functions create an MCP client instance.
+
+
+
Check out the corresponding examples at: [examples/simple-mcp-client](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client) and [examples/simple-mcp-client-core](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client-core).
+
+## Projects using Rust MCP SDK
+
+Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
+
+| Icon | Name | Description | Link |
+|------|------|-------------|------|
+|
| [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
+|
| [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
+
+
## Contributing
We welcome everyone who wishes to contribute! Please refer to the [contributing](CONTRIBUTING.md) guidelines for more details.
diff --git a/assets/examples/hello-world-server-sse.gif b/assets/examples/hello-world-server-sse.gif
new file mode 100644
index 0000000..87de711
Binary files /dev/null and b/assets/examples/hello-world-server-sse.gif differ
diff --git a/assets/examples/simple-mcp-client-sse.png b/assets/examples/simple-mcp-client-sse.png
new file mode 100644
index 0000000..37a80fb
Binary files /dev/null and b/assets/examples/simple-mcp-client-sse.png differ
diff --git a/crates/rust-mcp-sdk/Cargo.toml b/crates/rust-mcp-sdk/Cargo.toml
index 98d10da..ab5c142 100644
--- a/crates/rust-mcp-sdk/Cargo.toml
+++ b/crates/rust-mcp-sdk/Cargo.toml
@@ -22,12 +22,35 @@ async-trait = { workspace = true }
futures = { workspace = true }
thiserror = { workspace = true }
+axum = { workspace = true, optional = true }
+uuid = { workspace = true, features = ["v4"], optional = true }
+tokio-stream = { workspace = true, optional = true }
+axum-server = { version = "0.7", features = [], optional = true }
+tracing.workspace = true
+
+# rustls = { workspace = true, optional = true }
+hyper = { version = "1.6.0" }
+
+[dev-dependencies]
+tracing-subscriber = { workspace = true, features = [
+ "env-filter",
+ "std",
+ "fmt",
+] }
+
[features]
-default = ["client", "server", "macros"] # All features enabled by default
-server = [] # Server feature
-client = [] # Client feature
+default = [
+ "client",
+ "server",
+ "macros",
+ "hyper-server",
+ "ssl",
+] # All features enabled by default
+server = [] # Server feature
+client = [] # Client feature
+hyper-server = ["axum", "axum-server", "uuid", "tokio-stream"]
+ssl = ["axum-server/tls-rustls"]
macros = ["rust-mcp-macros"]
-
[lints]
workspace = true
diff --git a/crates/rust-mcp-sdk/README.md b/crates/rust-mcp-sdk/README.md
index 119f2a2..b79bd66 100644
--- a/crates/rust-mcp-sdk/README.md
+++ b/crates/rust-mcp-sdk/README.md
@@ -9,29 +9,46 @@
[
](https://github.com/rust-mcp-stack/rust-mcp-sdk/actions/workflows/ci.yml)
[
-](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server#hello-world-mcp-server)
+](examples/hello-world-mcp-server)
-
-A high-performance, asynchronous toolkit for building MCP servers and clients.
+A high-performance, asynchronous toolkit for building MCP servers and clients.
Focus on your app's logic while **rust-mcp-sdk** takes care of the rest!
-**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
+**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
Leveraging the [rust-mcp-schema](https://github.com/rust-mcp-stack/rust-mcp-schema) crate simplifies the process of building robust and reliable MCP servers and clients, ensuring consistency and minimizing errors in data handling and message processing.
-**⚠️WARNING**: This project only supports Standard Input/Output (stdio) transport at this time, with support for SSE (Server-Sent Events) transport still in progress and not yet available. Project is currently under development and should be used at your own risk.
+This project currently supports following transports:
+- **stdio** (Standard Input/Output)
+- **sse** (Server-Sent Events).
-## Projects using `rust-mcp-sdk`
-Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
-| Icon | Name | Description | Link |
-|------|------|-------------|------|
-|
| [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
-|
| [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
+🚀 The **rust-mcp-sdk** includes a lightweight [Axum](https://github.com/tokio-rs/axum) based server that handles all core functionality seamlessly. Switching between `stdio` and `sse` is straightforward, requiring minimal code changes. The server is designed to efficiently handle multiple concurrent client connections and offers built-in support for SSL.
+
+**⚠️** **Streamable HTTP** transport and authentication still in progress and not yet available. Project is currently under development and should be used at your own risk.
+
+## Table of Contents
+- [Usage Examples](#usage-examples)
+ - [MCP Server (stdio)](#mcp-server-stdio)
+ - [MCP Server (sse)](#mcp-server-sse)
+ - [MCP Client (stdio)](#mcp-client-stdio)
+ - [MCP Client (sse)](#mcp-client-sse)
+- [Cargo features](#cargo-features)
+ - [Available Features](#available-features)
+ - [Default Features](#default-features)
+ - [Using Only the server Features](#using-only-the-server-features)
+ - [Using Only the client Features](#using-only-the-client-features)
+- [Choosing Between Standard and Core Handlers traits](#choosing-between-standard-and-core-handlers-traits)
+ - [Choosing Between **ServerHandler** and **ServerHandlerCore**](#choosing-between-serverhandler-and-serverhandlercore)
+ - [Choosing Between **ClientHandler** and **ClientHandlerCore**](#choosing-between-clienthandler-and-clienthandlercore)
+- [Projects using Rust MCP SDK](#projects-using-rust-mcp-sdk)
+- [Contributing](#contributing)
+- [Development](#development)
+- [License](#license)
## Usage Examples
-### MCP Server
+### MCP Server (stdio)
Create a MCP server with a `tool` that will print a `Hello World!` message:
@@ -71,7 +88,55 @@ async fn main() -> SdkResult<()> {
}
```
-The implementation of `MyServerHandler` could be as simple as the following:
+See hello-world-mcp-server example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
+
+
+
+### MCP Server (sse)
+
+Creating an MCP server in `rust-mcp-sdk` with the `sse` transport allows multiple clients to connect simultaneously with no additional setup.
+Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and transform options.
+
+```rust
+
+// STEP 1: Define server details and capabilities
+let server_details = InitializeResult {
+ // server name and version
+ server_info: Implementation {
+ name: "Hello World MCP Server".to_string(),
+ version: "0.1.0".to_string(),
+ },
+ capabilities: ServerCapabilities {
+ // indicates that server support mcp tools
+ tools: Some(ServerCapabilitiesTools { list_changed: None }),
+ ..Default::default() // Using default values for other fields
+ },
+ meta: None,
+ instructions: Some("server instructions...".to_string()),
+ protocol_version: LATEST_PROTOCOL_VERSION.to_string(),
+};
+
+// STEP 2: instantiate our custom handler for handling MCP messages
+let handler = MyServerHandler {};
+
+// STEP 3: instantiate HyperServer, providing `server_details` , `handler` and HyperServerOptions
+let server = hyper_server::create_server(
+ server_details,
+ handler,
+ HyperServerOptions {
+ host: "127.0.0.1".to_string(),
+ ..Default::default()
+ },
+);
+
+// STEP 4: Start the server
+server.start().await?;
+
+Ok(())
+```
+
+
+The implementation of `MyServerHandler` is the same regardless of the transport used and could be as simple as the following:
```rust
@@ -117,13 +182,13 @@ impl ServerHandler for MyServerHandler {
👉 For a more detailed example of a [Hello World MCP](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server) Server that supports multiple tools and provides more type-safe handling of `CallToolRequest`, check out: **[examples/hello-world-mcp-server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server)**
-See hello-world-mcp-server example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
+See hello-world-server-sse example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
-
+
---
-### MCP Client
+### MCP Client (stdio)
Create an MCP client that starts the [@modelcontextprotocol/server-everything](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) server, displays the server's name, version, and list of tools, then uses the add tool provided by the server to sum 120 and 28, printing the result.
@@ -204,23 +269,38 @@ Here is the output :
> your results may vary slightly depending on the version of the MCP Server in use when you run it.
+### MCP Client (sse)
+Creating an MCP client using the `rust-mcp-sdk` with the SSE transport is almost identical, with one exception at `step 3`. Instead of creating a `StdioTransport`, you simply create a `ClientSseTransport`. The rest of the code remains the same:
+
+```diff
+- let transport = StdioTransport::create_with_server_launch(
+- "npx",
+- vec![ "-y".to_string(), "@modelcontextprotocol/server-everything".to_string()],
+- None, TransportOptions::default()
+-)?;
++ let transport = ClientSseTransport::new(MCP_SERVER_URL, ClientSseTransportOptions::default())?;
+```
+
+
## Getting Started
If you are looking for a step-by-step tutorial on how to get started with `rust-mcp-sdk` , please see : [Getting Started MCP Server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/doc/getting-started-mcp-server.md)
-## Features
+## Cargo Features
-The `rust-mcp-sdk` crate provides three optional features: `server` , `client` and `macros`. By default, all features are enabled for maximum functionality. You can customize which features to include based on your project's needs.
+The `rust-mcp-sdk` crate provides several features that can be enabled or disabled. By default, all features are enabled to ensure maximum functionality, but you can customize which ones to include based on your project's requirements.
### Available Features
-- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP services.
+- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP servers.
- `client`: Activates MCP client capabilities, offering modules and APIs for client development and communicating with MCP servers.
+- `hyper-server`: This feature enables the **sse** transport for MCP servers, supporting multiple simultaneous client connections out of the box.
+- `ssl`: This feature enables TLS/SSL support for the **sse** transport when used with the `hyper-server`.
- `macros`: Provides procedural macros for simplifying the creation and manipulation of MCP Tool structures.
-### Default Behavior
+### Default Features
-All features (server, client, and macros) are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
+All features are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
@@ -231,7 +311,7 @@ rust-mcp-sdk = "0.2.0"
-### Using Only the server Feature
+### Using Only the server Features
If you only need the MCP Server functionality, you can disable the default features and explicitly enable the server feature. Add the following to your Cargo.toml:
@@ -241,10 +321,11 @@ If you only need the MCP Server functionality, you can disable the default featu
[dependencies]
rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["server","macros"] }
```
+Optionally add `hyper-server` for **sse** transport, and `ssl` feature for tls/ssl support of the `hyper-server`
-### Using Only the client Feature
+### Using Only the client Features
If you only need the MCP Client functionality, you can disable the default features and explicitly enable the client feature. Add the following to your Cargo.toml:
@@ -257,28 +338,59 @@ rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["clien
-### Choosing Between `mcp_server_handler` and `mcp_server_handler_core`
+## Choosing Between Standard and Core Handlers traits
+Learn when to use the `mcp_*_handler` traits versus the lower-level `mcp_*_handler_core` traits for both server and client implementations. This section helps you decide based on your project's need for simplicity versus fine-grained control.
+
+### Choosing Between `ServerHandler` and `ServerHandlerCore`
[rust-mcp-sdk](https://github.com/rust-mcp-stack/rust-mcp-sdk) provides two type of handler traits that you can chose from:
-- **mcp_server_handler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
+- **ServerHandler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
Refer to [examples/hello-world-mcp-server/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server/src/handler.rs) for an example.
-- **mcp_server_handler_core**: If you need more control over MCP messages, consider using `mcp_server_handler_core`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
+- **ServerHandlerCore**: If you need more control over MCP messages, consider using `ServerHandlerCore`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
Refer to [examples/hello-world-mcp-server-core/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server-core/src/handler.rs) for an example.
---
-**👉 Note:** Depending on your choice between `mcp_server_handler` and `mcp_server_handler_core`, you must use either `server_runtime::create_server()` or `server_runtime_core::create_server()` , respectively.
+**👉 Note:** Depending on whether you choose `ServerHandler` or `ServerHandlerCore`, you must use the `create_server()` function from the appropriate module:
+
+- For `ServerHandler`:
+ - Use `server_runtime::create_server()` for servers with stdio transport
+ - Use `hyper_server::create_server()` for servers with sse transport
+
+- For `ServerHandlerCore`:
+ - Use `server_runtime_core::create_server()` for servers with stdio transport
+ - Use `hyper_server_core::create_server()` for servers with sse transport
---
-### Choosing Between `mcp_client_handler` and `mcp_client_handler_core`
-The same principles outlined above apply to the client-side handlers, `mcp_client_handler` and `mcp_client_handler_core`.
-Use `client_runtime::create_client()` or `client_runtime_core::create_client()` , respectively.
+### Choosing Between `ClientHandler` and `ClientHandlerCore`
+
+The same principles outlined above apply to the client-side handlers, `ClientHandler` and `ClientHandlerCore`.
+
+- Use `client_runtime::create_client()` when working with `ClientHandler`
+
+- Use `client_runtime_core::create_client()` when working with `ClientHandlerCore`
+
+Both functions create an MCP client instance.
+
+
+
Check out the corresponding examples at: [examples/simple-mcp-client](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client) and [examples/simple-mcp-client-core](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client-core).
+
+## Projects using Rust MCP SDK
+
+Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
+
+| Icon | Name | Description | Link |
+|------|------|-------------|------|
+|
| [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
+|
| [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
+
+
## Contributing
We welcome everyone who wishes to contribute! Please refer to the [contributing](CONTRIBUTING.md) guidelines for more details.
diff --git a/crates/rust-mcp-sdk/assets/examples/hello-world-server-sse.gif b/crates/rust-mcp-sdk/assets/examples/hello-world-server-sse.gif
new file mode 100644
index 0000000..87de711
Binary files /dev/null and b/crates/rust-mcp-sdk/assets/examples/hello-world-server-sse.gif differ
diff --git a/crates/rust-mcp-sdk/assets/examples/simple-mcp-client-sse.png b/crates/rust-mcp-sdk/assets/examples/simple-mcp-client-sse.png
new file mode 100644
index 0000000..37a80fb
Binary files /dev/null and b/crates/rust-mcp-sdk/assets/examples/simple-mcp-client-sse.png differ
diff --git a/crates/rust-mcp-sdk/src/error.rs b/crates/rust-mcp-sdk/src/error.rs
index c6ca132..3b2f00d 100644
--- a/crates/rust-mcp-sdk/src/error.rs
+++ b/crates/rust-mcp-sdk/src/error.rs
@@ -2,6 +2,9 @@ use rust_mcp_schema::RpcError;
use rust_mcp_transport::error::TransportError;
use thiserror::Error;
+#[cfg(feature = "hyper-server")]
+use crate::hyper_servers::error::TransportServerError;
+
pub type SdkResult = core::result::Result;
#[derive(Debug, Error)]
@@ -18,6 +21,9 @@ pub enum McpSdkError {
AnyError(Box<(dyn std::error::Error + Send + Sync)>),
#[error("{0}")]
SdkError(#[from] rust_mcp_schema::schema_utils::SdkError),
+ #[cfg(feature = "hyper-server")]
+ #[error("{0}")]
+ TransportServerError(#[from] TransportServerError),
}
#[deprecated(since = "0.2.0", note = "Use `McpSdkError` instead.")]
diff --git a/crates/rust-mcp-sdk/src/hyper_servers.rs b/crates/rust-mcp-sdk/src/hyper_servers.rs
new file mode 100644
index 0000000..ad1e2cd
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers.rs
@@ -0,0 +1,10 @@
+mod app_state;
+pub mod error;
+pub mod hyper_server;
+pub mod hyper_server_core;
+mod routes;
+mod server;
+mod session_store;
+
+pub use server::*;
+pub use session_store::*;
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/app_state.rs b/crates/rust-mcp-sdk/src/hyper_servers/app_state.rs
new file mode 100644
index 0000000..3276802
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/app_state.rs
@@ -0,0 +1,22 @@
+use std::{sync::Arc, time::Duration};
+
+use rust_mcp_schema::InitializeResult;
+use rust_mcp_transport::TransportOptions;
+
+use crate::mcp_traits::mcp_handler::McpServerHandler;
+
+use super::{session_store::SessionStore, IdGenerator};
+
+/// Application state struct for the Hyper server
+///
+/// Holds shared, thread-safe references to session storage, ID generator,
+/// server details, handler, ping interval, and transport options.
+#[derive(Clone)]
+pub struct AppState {
+ pub session_store: Arc,
+ pub id_generator: Arc,
+ pub server_details: Arc,
+ pub handler: Arc,
+ pub ping_interval: Duration,
+ pub transport_options: Arc,
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/error.rs b/crates/rust-mcp-sdk/src/hyper_servers/error.rs
new file mode 100644
index 0000000..adcccf4
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/error.rs
@@ -0,0 +1,33 @@
+use std::net::AddrParseError;
+
+use axum::{http::StatusCode, response::IntoResponse};
+use thiserror::Error;
+
+pub type TransportServerResult = core::result::Result;
+
+#[derive(Debug, Error, Clone)]
+pub enum TransportServerError {
+ #[error("'sessionId' query string is missing!")]
+ SessionIdMissing,
+ #[error("No session found for the given ID: {0}.")]
+ SessionIdInvalid(String),
+ #[error("Stream IO Error: {0}.")]
+ StreamIoError(String),
+ #[error("{0}")]
+ AddrParseError(#[from] AddrParseError),
+ #[error("Server start error: {0}")]
+ ServerStartError(String),
+ #[error("Invalid options: {0}")]
+ InvalidServerOptions(String),
+ #[error("{0}")]
+ SslCertError(String),
+}
+
+impl IntoResponse for TransportServerError {
+ //consume self and returns a Response
+ fn into_response(self) -> axum::response::Response {
+ let mut response = StatusCode::INTERNAL_SERVER_ERROR.into_response();
+ response.extensions_mut().insert(self);
+ response
+ }
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/hyper_server.rs b/crates/rust-mcp-sdk/src/hyper_servers/hyper_server.rs
new file mode 100644
index 0000000..eb88feb
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/hyper_server.rs
@@ -0,0 +1,29 @@
+use std::sync::Arc;
+
+use rust_mcp_schema::InitializeResult;
+
+use crate::mcp_server::{server_runtime::ServerRuntimeInternalHandler, ServerHandler};
+
+use super::{HyperServer, HyperServerOptions};
+
+/// Creates a new HyperServer instance with the provided handler and options
+/// The handler must implement ServerHandler.
+///
+/// # Arguments
+/// * `server_details` - Initialization result from the MCP schema
+/// * `handler` - Implementation of the ServerHandlerCore trait
+/// * `server_options` - Configuration options for the HyperServer
+///
+/// # Returns
+/// * `HyperServer` - A configured HyperServer instance ready to start
+pub fn create_server(
+ server_details: InitializeResult,
+ handler: impl ServerHandler,
+ server_options: HyperServerOptions,
+) -> HyperServer {
+ HyperServer::new(
+ server_details,
+ Arc::new(ServerRuntimeInternalHandler::new(Box::new(handler))),
+ server_options,
+ )
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/hyper_server_core.rs b/crates/rust-mcp-sdk/src/hyper_servers/hyper_server_core.rs
new file mode 100644
index 0000000..d0663f3
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/hyper_server_core.rs
@@ -0,0 +1,26 @@
+use super::{HyperServer, HyperServerOptions};
+use crate::mcp_server::{server_runtime_core::RuntimeCoreInternalHandler, ServerHandlerCore};
+use rust_mcp_schema::InitializeResult;
+use std::sync::Arc;
+
+/// Creates a new HyperServer instance with the provided handler and options
+/// The handler must implement ServerHandlerCore.
+///
+/// # Arguments
+/// * `server_details` - Initialization result from the MCP schema
+/// * `handler` - Implementation of the ServerHandlerCore trait
+/// * `server_options` - Configuration options for the HyperServer
+///
+/// # Returns
+/// * `HyperServer` - A configured HyperServer instance ready to start
+pub fn create_server(
+ server_details: InitializeResult,
+ handler: impl ServerHandlerCore,
+ server_options: HyperServerOptions,
+) -> HyperServer {
+ HyperServer::new(
+ server_details,
+ Arc::new(RuntimeCoreInternalHandler::new(Box::new(handler))),
+ server_options,
+ )
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/routes.rs b/crates/rust-mcp-sdk/src/hyper_servers/routes.rs
new file mode 100644
index 0000000..7146880
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/routes.rs
@@ -0,0 +1,29 @@
+pub mod fallback_routes;
+pub mod messages_routes;
+pub mod sse_routes;
+
+use super::{app_state::AppState, HyperServerOptions};
+use axum::Router;
+use std::sync::Arc;
+
+/// Constructs the Axum router with all application routes
+///
+/// Combines routes for Server-Sent Events, message handling, and fallback routes,
+/// attaching the shared application state to the router.
+///
+/// # Arguments
+/// * `state` - Shared application state wrapped in an Arc
+/// * `server_options` - Reference to the HyperServer configuration options
+///
+/// # Returns
+/// * `Router` - An Axum router configured with all application routes and state
+pub fn app_routes(state: Arc, server_options: &HyperServerOptions) -> Router {
+ Router::new()
+ .merge(sse_routes::routes(
+ state.clone(),
+ server_options.sse_endpoint(),
+ ))
+ .merge(messages_routes::routes(state.clone()))
+ .with_state(state)
+ .merge(fallback_routes::routes())
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/routes/fallback_routes.rs b/crates/rust-mcp-sdk/src/hyper_servers/routes/fallback_routes.rs
new file mode 100644
index 0000000..d6ae240
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/routes/fallback_routes.rs
@@ -0,0 +1,15 @@
+use axum::{
+ http::{StatusCode, Uri},
+ Router,
+};
+
+pub fn routes() -> Router {
+ Router::new().fallback(not_found)
+}
+
+pub async fn not_found(uri: Uri) -> (StatusCode, String) {
+ (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ format!("Server Error!\r\n uri: {}", uri),
+ )
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/routes/messages_routes.rs b/crates/rust-mcp-sdk/src/hyper_servers/routes/messages_routes.rs
new file mode 100644
index 0000000..10e2eb9
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/routes/messages_routes.rs
@@ -0,0 +1,50 @@
+use crate::hyper_servers::{
+ app_state::AppState,
+ error::{TransportServerError, TransportServerResult},
+};
+use axum::{
+ extract::{Query, State},
+ response::IntoResponse,
+ routing::post,
+ Router,
+};
+use std::{collections::HashMap, sync::Arc};
+use tokio::io::AsyncWriteExt;
+
+const SSE_MESSAGES_PATH: &str = "/messages";
+
+pub fn routes(_state: Arc) -> Router> {
+ Router::new().route(SSE_MESSAGES_PATH, post(handle_messages))
+}
+
+pub async fn handle_messages(
+ State(state): State>,
+ Query(params): Query>,
+ message: String,
+) -> TransportServerResult {
+ let session_id = params
+ .get("sessionId")
+ .ok_or(TransportServerError::SessionIdMissing)?;
+
+ let transmit =
+ state
+ .session_store
+ .get(session_id)
+ .await
+ .ok_or(TransportServerError::SessionIdInvalid(
+ session_id.to_string(),
+ ))?;
+ let mut transmit = transmit.lock().await;
+
+ transmit
+ .write_all(format!("{message}\n").as_bytes())
+ .await
+ .map_err(|err| TransportServerError::StreamIoError(err.to_string()))?;
+
+ transmit
+ .flush()
+ .await
+ .map_err(|err| TransportServerError::StreamIoError(err.to_string()))?;
+
+ Ok(axum::http::StatusCode::OK)
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/routes/sse_routes.rs b/crates/rust-mcp-sdk/src/hyper_servers/routes/sse_routes.rs
new file mode 100644
index 0000000..2efe3be
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/routes/sse_routes.rs
@@ -0,0 +1,167 @@
+use crate::{
+ error::McpSdkError,
+ hyper_servers::{app_state::AppState, error::TransportServerResult},
+ mcp_server::{server_runtime, ServerRuntime},
+ mcp_traits::mcp_handler::McpServerHandler,
+ McpServer,
+};
+use axum::{
+ extract::State,
+ response::{
+ sse::{Event, KeepAlive},
+ IntoResponse, Sse,
+ },
+ routing::get,
+ Router,
+};
+use futures::stream::{self};
+use rust_mcp_transport::{error::TransportError, SseTransport};
+use std::{convert::Infallible, sync::Arc, time::Duration};
+use tokio::{
+ io::{duplex, AsyncBufReadExt, BufReader},
+ time::{self, Interval},
+};
+use tokio_stream::StreamExt;
+
+const SSE_MESSAGES_PATH: &str = "/messages";
+const CLIENT_PING_TIMEOUT: Duration = Duration::from_secs(2);
+
+const DUPLEX_BUFFER_SIZE: usize = 8192;
+
+/// Creates an initial SSE event that returns the messages endpoint
+///
+/// Constructs an SSE event containing the messages endpoint URL with the session ID.
+///
+/// # Arguments
+/// * `session_id` - The session identifier for the client
+///
+/// # Returns
+/// * `Result` - The constructed SSE event, infallible
+fn initial_event(session_id: &str) -> Result {
+ Ok(Event::default()
+ .event("endpoint")
+ .data(format!("{SSE_MESSAGES_PATH}?sessionId={session_id}")))
+}
+
+/// Configures the SSE routes for the application
+///
+/// Sets up the Axum router with a single GET route for the specified SSE endpoint.
+///
+/// # Arguments
+/// * `_state` - Shared application state (not used directly in routing)
+/// * `sse_endpoint` - The path for the SSE endpoint
+///
+/// # Returns
+/// * `Router>` - An Axum router configured with the SSE route
+pub fn routes(_state: Arc, sse_endpoint: &str) -> Router> {
+ Router::new().route(sse_endpoint, get(handle_sse))
+}
+
+/// Handles Server-Sent Events (SSE) connections
+///
+/// Establishes an SSE connection, sets up a server instance, and streams messages
+/// to the client. Manages session creation, periodic pings, and server lifecycle.
+///
+/// # Arguments
+/// * `State(state)` - Extracted application state
+///
+/// # Returns
+/// * `TransportServerResult` - The SSE response stream or an error
+pub async fn handle_sse(
+ State(state): State>,
+) -> TransportServerResult {
+ // readable stream of string to be used in transport
+ let (read_tx, read_rx) = duplex(DUPLEX_BUFFER_SIZE);
+ // writable stream to deliver message to the client
+ let (write_tx, write_rx) = duplex(DUPLEX_BUFFER_SIZE);
+
+ // generate a session id, and keep it in the server state
+ let session_id = state.id_generator.generate();
+ state
+ .session_store
+ .set(session_id.to_owned(), read_tx)
+ .await;
+
+ // create a transport for sending/receiving messages
+ let transport =
+ SseTransport::new(read_rx, write_tx, Arc::clone(&state.transport_options)).unwrap();
+ let d: Arc = state.handler.clone();
+ // create a new server instance with unique session_id and
+ let server: Arc = Arc::new(server_runtime::create_server_instance(
+ Arc::clone(&state.server_details),
+ transport,
+ d,
+ session_id.to_owned(),
+ ));
+
+ // Ping the server periodically to check if the SSE client is still connected
+ let server_ping = Arc::clone(&server);
+ tokio::spawn(async move {
+ let mut interval: Interval = time::interval(state.ping_interval);
+ loop {
+ interval.tick().await; // Wait for the next tick (10 seconds)
+ if !server_ping.is_initialized() {
+ continue;
+ }
+ match server_ping.ping(Some(CLIENT_PING_TIMEOUT)).await {
+ Ok(_) => {}
+ Err(McpSdkError::TransportError(TransportError::StdioError(error))) => {
+ if error.kind() == std::io::ErrorKind::BrokenPipe {
+ if let Some(session_id) = server_ping.session_id().await {
+ tracing::info!("Stopping {} server task ...", session_id);
+ state.session_store.delete(&session_id).await;
+ break;
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ });
+
+ tracing::info!(
+ "A new client joined : {}",
+ server.session_id().await.unwrap_or_default().to_owned()
+ );
+
+ // Start the server
+ tokio::spawn(async move {
+ match server.start().await {
+ Ok(_) => tracing::info!(
+ "server {} exited gracefully.",
+ server.session_id().await.unwrap_or_default().to_owned()
+ ),
+ Err(err) => tracing::info!(
+ "server {} exited with error : {}",
+ server.session_id().await.unwrap_or_default().to_owned(),
+ err
+ ),
+ }
+ });
+
+ // Initial SSE message to inform the client about the server's endpoint
+ let initial_event = stream::once(async move { initial_event(&session_id) });
+
+ // Construct SSE stream for sending MCP messages to the server
+ let reader = BufReader::new(write_rx);
+
+ let message_stream = stream::unfold(reader, |mut reader| async move {
+ let mut line = String::new();
+
+ match reader.read_line(&mut line).await {
+ Ok(0) => None, // EOF
+ Ok(_) => {
+ let trimmed_line = line.trim_end_matches('\n').to_owned();
+ Some((Ok(Event::default().data(trimmed_line)), reader))
+ }
+ Err(_) => None, // Err(e) => Some((Err(e), reader)),
+ }
+ });
+
+ let stream = initial_event.chain(message_stream);
+ let sse_stream =
+ Sse::new(stream).keep_alive(KeepAlive::new().interval(Duration::from_secs(10)));
+
+ // Return SSE response with keep-alive
+ Ok(sse_stream)
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/server.rs b/crates/rust-mcp-sdk/src/hyper_servers/server.rs
new file mode 100644
index 0000000..f0770e1
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/server.rs
@@ -0,0 +1,312 @@
+use crate::mcp_traits::mcp_handler::McpServerHandler;
+#[cfg(feature = "ssl")]
+use axum_server::tls_rustls::RustlsConfig;
+use std::{
+ net::{SocketAddr, ToSocketAddrs},
+ path::Path,
+ sync::Arc,
+ time::Duration,
+};
+
+use super::{
+ app_state::AppState,
+ error::{TransportServerError, TransportServerResult},
+ routes::app_routes,
+ InMemorySessionStore, UuidGenerator,
+};
+use axum::Router;
+use rust_mcp_schema::InitializeResult;
+use rust_mcp_transport::TransportOptions;
+
+// Default client ping interval (12 seconds)
+const DEFAULT_CLIENT_PING_INTERVAL: Duration = Duration::from_secs(12);
+
+// Default Server-Sent Events (SSE) endpoint path
+const DEFAULT_SSE_ENDPOINT: &str = "/sse";
+
+/// Configuration struct for the Hyper server
+/// Used to configure the HyperServer instance.
+pub struct HyperServerOptions {
+ /// Hostname or IP address the server will bind to (default: "localhost")
+ pub host: String,
+ /// Hostname or IP address the server will bind to (default: "localhost")
+ pub port: u16,
+ /// Optional custom path for the Server-Sent Events (SSE) endpoint.
+ /// If `None`, the default path `/sse` will be used.
+ pub custom_sse_endpoint: Option,
+ /// Interval between automatic ping messages sent to clients to detect disconnects
+ pub ping_interval: Duration,
+ /// Enables SSL/TLS if set to `true`
+ pub enable_ssl: bool,
+ /// Path to the SSL/TLS certificate file (e.g., "cert.pem").
+ /// Required if `enable_ssl` is `true`.
+ pub ssl_cert_path: Option,
+ /// Path to the SSL/TLS private key file (e.g., "key.pem").
+ /// Required if `enable_ssl` is `true`.
+ pub ssl_key_path: Option,
+ /// Shared transport configuration used by the server
+ pub transport_options: Arc,
+}
+
+impl HyperServerOptions {
+ /// Validates the server configuration options
+ ///
+ /// Ensures that SSL-related paths are provided and valid when SSL is enabled.
+ ///
+ /// # Returns
+ /// * `TransportServerResult<()>` - Ok if validation passes, Err with TransportServerError if invalid
+ pub fn validate(&self) -> TransportServerResult<()> {
+ if self.enable_ssl {
+ if self.ssl_cert_path.is_none() || self.ssl_key_path.is_none() {
+ return Err(TransportServerError::InvalidServerOptions(
+ "Both 'ssl_cert_path' and 'ssl_key_path' must be provided when SSL is enabled."
+ .into(),
+ ));
+ }
+
+ if !Path::new(self.ssl_cert_path.as_deref().unwrap_or("")).is_file() {
+ return Err(TransportServerError::InvalidServerOptions(
+ "'ssl_cert_path' does not point to a valid or existing file.".into(),
+ ));
+ }
+
+ if !Path::new(self.ssl_key_path.as_deref().unwrap_or("")).is_file() {
+ return Err(TransportServerError::InvalidServerOptions(
+ "'ssl_key_path' does not point to a valid or existing file.".into(),
+ ));
+ }
+ }
+
+ Ok(())
+ }
+
+ /// Resolves the server address from host and port
+ ///
+ /// Validates the configuration and converts the host/port into a SocketAddr.
+ /// Handles scheme prefixes (http:// or https://) and logs warnings for mismatches.
+ ///
+ /// # Returns
+ /// * `TransportServerResult` - The resolved server address or an error
+ async fn resolve_server_address(&self) -> TransportServerResult {
+ self.validate()?;
+
+ let mut host = self.host.to_string();
+ if let Some(stripped) = self.host.strip_prefix("http://") {
+ if self.enable_ssl {
+ tracing::warn!("Warning: Ignoring http:// scheme for SSL; using hostname only");
+ }
+ host = stripped.to_string();
+ } else if let Some(stripped) = host.strip_prefix("https://") {
+ host = stripped.to_string();
+ }
+
+ let addr = {
+ let mut iter = (host, self.port)
+ .to_socket_addrs()
+ .map_err(|err| TransportServerError::ServerStartError(err.to_string()))?;
+ match iter.next() {
+ Some(addr) => addr,
+ None => format!("{}:{}", self.host, self.port).parse().map_err(
+ |err: std::net::AddrParseError| {
+ TransportServerError::ServerStartError(err.to_string())
+ },
+ )?,
+ }
+ };
+ Ok(addr)
+ }
+
+ pub fn sse_endpoint(&self) -> &str {
+ self.custom_sse_endpoint
+ .as_deref()
+ .unwrap_or(DEFAULT_SSE_ENDPOINT)
+ }
+}
+
+/// Default implementation for HyperServerOptions
+///
+/// Provides default values for the server configuration, including localhost address,
+/// port 8080, default SSE endpoint, and 12-second ping interval.
+impl Default for HyperServerOptions {
+ fn default() -> Self {
+ Self {
+ host: "127.0.0.1".to_string(),
+ port: 8080,
+ custom_sse_endpoint: None,
+ ping_interval: DEFAULT_CLIENT_PING_INTERVAL,
+ transport_options: Default::default(),
+ enable_ssl: false,
+ ssl_cert_path: None,
+ ssl_key_path: None,
+ }
+ }
+}
+
+/// Hyper server struct for managing the Axum-based web server
+pub struct HyperServer {
+ app: Router,
+ state: Arc,
+ options: HyperServerOptions,
+}
+
+impl HyperServer {
+ /// Creates a new HyperServer instance
+ ///
+ /// Initializes the server with the provided server details, handler, and options.
+ ///
+ /// # Arguments
+ /// * `server_details` - Initialization result from the MCP schema
+ /// * `handler` - Shared MCP server handler with static lifetime
+ /// * `server_options` - Server configuration options
+ ///
+ /// # Returns
+ /// * `Self` - A new HyperServer instance
+ pub(crate) fn new(
+ server_details: InitializeResult,
+ handler: Arc,
+ server_options: HyperServerOptions,
+ ) -> Self {
+ let state: Arc = Arc::new(AppState {
+ session_store: Arc::new(InMemorySessionStore::new()),
+ id_generator: Arc::new(UuidGenerator {}),
+ server_details: Arc::new(server_details),
+ handler,
+ ping_interval: server_options.ping_interval,
+ transport_options: Arc::clone(&server_options.transport_options),
+ });
+ let app = app_routes(Arc::clone(&state), &server_options);
+ Self {
+ app,
+ state,
+ options: server_options,
+ }
+ }
+
+ /// Returns a shared reference to the application state
+ ///
+ /// # Returns
+ /// * `Arc` - Shared application state
+ pub fn state(&self) -> Arc {
+ Arc::clone(&self.state)
+ }
+
+ /// Adds a new route to the server
+ ///
+ /// # Arguments
+ /// * `path` - The route path (static string)
+ /// * `route` - The Axum MethodRouter for handling the route
+ ///
+ /// # Returns
+ /// * `Self` - The modified HyperServer instance
+ pub fn with_route(mut self, path: &'static str, route: axum::routing::MethodRouter) -> Self {
+ self.app = self.app.route(path, route);
+ self
+ }
+
+ /// Generates server information string
+ ///
+ /// Constructs a string describing the server type, protocol, address, and SSE endpoint.
+ ///
+ /// # Arguments
+ /// * `addr` - Optional SocketAddr; if None, resolves from options
+ ///
+ /// # Returns
+ /// * `TransportServerResult` - The server information string or an error
+ pub async fn server_info(&self, addr: Option) -> TransportServerResult {
+ let addr = addr.unwrap_or(self.options.resolve_server_address().await?);
+ let server_type = if self.options.enable_ssl {
+ "SSL server"
+ } else {
+ "Server"
+ };
+ let protocol = if self.options.enable_ssl {
+ "https"
+ } else {
+ "http"
+ };
+
+ let server_url = format!(
+ "{} is available at {}://{}{}",
+ server_type,
+ protocol,
+ addr,
+ self.options.sse_endpoint()
+ );
+
+ Ok(server_url)
+ }
+
+ // pub fn with_layer(mut self, layer: L) -> Self
+ // where
+ // // L: Layer + Clone + Send + Sync + 'static,
+ // L::Service: Send + Sync + 'static,
+ // {
+ // self.router = self.router.layer(layer);
+ // self
+ // }
+
+ /// Starts the server with SSL support (available when "ssl" feature is enabled)
+ ///
+ /// # Arguments
+ /// * `addr` - The server address to bind to
+ ///
+ /// # Returns
+ /// * `TransportServerResult<()>` - Ok if the server starts successfully, Err otherwise
+ #[cfg(feature = "ssl")]
+ async fn start_ssl(self, addr: SocketAddr) -> TransportServerResult<()> {
+ let config = RustlsConfig::from_pem_file(
+ self.options.ssl_cert_path.as_deref().unwrap_or_default(),
+ self.options.ssl_key_path.as_deref().unwrap_or_default(),
+ )
+ .await
+ .map_err(|err| TransportServerError::SslCertError(err.to_string()))?;
+
+ tracing::info!("{}", self.server_info(Some(addr)).await?);
+
+ axum_server::bind_rustls(addr, config)
+ .serve(self.app.into_make_service())
+ .await
+ .map_err(|err| TransportServerError::ServerStartError(err.to_string()))
+ }
+
+ /// Starts the server without SSL
+ ///
+ /// # Arguments
+ /// * `addr` - The server address to bind to
+ ///
+ /// # Returns
+ /// * `TransportServerResult<()>` - Ok if the server starts successfully, Err otherwise
+ async fn start_http(self, addr: SocketAddr) -> TransportServerResult<()> {
+ tracing::info!("{}", self.server_info(Some(addr)).await?);
+
+ axum_server::bind(addr)
+ .serve(self.app.into_make_service())
+ .await
+ .map_err(|err| TransportServerError::ServerStartError(err.to_string()))
+ }
+
+ /// Starts the server, choosing SSL or HTTP based on configuration
+ ///
+ /// Resolves the server address and starts the server in either SSL or HTTP mode.
+ /// Panics if SSL is requested but the "ssl" feature is not enabled.
+ ///
+ /// # Returns
+ /// * `TransportServerResult<()>` - Ok if the server starts successfully, Err otherwise
+ pub async fn start(self) -> TransportServerResult<()> {
+ let addr = self.options.resolve_server_address().await?;
+
+ #[cfg(feature = "ssl")]
+ if self.options.enable_ssl {
+ self.start_ssl(addr).await
+ } else {
+ self.start_http(addr).await
+ }
+
+ #[cfg(not(feature = "ssl"))]
+ if self.options.enable_ssl {
+ panic!("SSL requested but the 'ssl' feature is not enabled");
+ } else {
+ self.start_http(addr).await
+ }
+ }
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/session_store.rs b/crates/rust-mcp-sdk/src/hyper_servers/session_store.rs
new file mode 100644
index 0000000..da25000
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/session_store.rs
@@ -0,0 +1,65 @@
+mod in_memory;
+use std::sync::Arc;
+
+use async_trait::async_trait;
+pub use in_memory::*;
+use tokio::{io::DuplexStream, sync::Mutex};
+use uuid::Uuid;
+
+// Type alias for the server-side duplex stream used in sessions
+pub type TxServer = DuplexStream;
+
+// Type alias for session identifier, represented as a String
+pub type SessionId = String;
+
+/// Trait defining the interface for session storage operations
+///
+/// This trait provides asynchronous methods for managing session data,
+/// Implementors must be Send and Sync to support concurrent access.
+#[async_trait]
+pub trait SessionStore: Send + Sync {
+ /// Retrieves a session by its identifier
+ ///
+ /// # Arguments
+ /// * `key` - The session identifier to look up
+ ///
+ /// # Returns
+ /// * `Option>>` - The session stream wrapped in `Arc` if found, None otherwise
+ async fn get(&self, key: &SessionId) -> Option>>;
+ /// Stores a new session with the given identifier
+ ///
+ /// # Arguments
+ /// * `key` - The session identifier
+ /// * `value` - The duplex stream to store
+ async fn set(&self, key: SessionId, value: TxServer);
+ /// Deletes a session by its identifier
+ ///
+ /// # Arguments
+ /// * `key` - The session identifier to delete
+ async fn delete(&self, key: &SessionId);
+ /// Clears all sessions from the store
+ async fn clear(&self);
+}
+
+/// Trait for generating session identifiers
+///
+/// Implementors must be Send and Sync to support concurrent access.
+pub trait IdGenerator: Send + Sync {
+ fn generate(&self) -> SessionId;
+}
+
+/// Struct implementing the IdGenerator trait using UUID v4
+///
+/// This is a simple wrapper around the uuid crate's Uuid::new_v4 function
+/// to generate unique session identifiers.
+pub struct UuidGenerator {}
+
+impl IdGenerator for UuidGenerator {
+ /// Generates a new UUID v4-based session identifier
+ ///
+ /// # Returns
+ /// * `SessionId` - A new UUID-based session identifier as a String
+ fn generate(&self) -> SessionId {
+ Uuid::new_v4().to_string()
+ }
+}
diff --git a/crates/rust-mcp-sdk/src/hyper_servers/session_store/in_memory.rs b/crates/rust-mcp-sdk/src/hyper_servers/session_store/in_memory.rs
new file mode 100644
index 0000000..7c5755d
--- /dev/null
+++ b/crates/rust-mcp-sdk/src/hyper_servers/session_store/in_memory.rs
@@ -0,0 +1,57 @@
+use super::SessionId;
+use super::{SessionStore, TxServer};
+use async_trait::async_trait;
+use std::collections::HashMap;
+use std::sync::Arc;
+use tokio::sync::Mutex;
+use tokio::sync::RwLock;
+
+/// In-memory session store implementation
+///
+/// Stores session data in a thread-safe HashMap, using a read-write lock for
+/// concurrent access and mutexes for individual session streams.
+#[derive(Clone, Default)]
+pub struct InMemorySessionStore {
+ store: Arc>>>>,
+}
+
+impl InMemorySessionStore {
+ /// Creates a new in-memory session store
+ ///
+ /// Initializes an empty HashMap wrapped in a read-write lock for thread-safe access.
+ ///
+ /// # Returns
+ /// * `Self` - A new InMemorySessionStore instance
+ pub fn new() -> Self {
+ Self {
+ store: Arc::new(RwLock::new(HashMap::new())),
+ }
+ }
+}
+
+/// Implementation of the SessionStore trait for InMemorySessionStore
+///
+/// Provides asynchronous methods for managing sessions in memory, ensuring
+/// thread-safety through read-write locks and mutexes.
+#[async_trait]
+impl SessionStore for InMemorySessionStore {
+ async fn get(&self, key: &SessionId) -> Option>> {
+ let store = self.store.read().await;
+ store.get(key).cloned()
+ }
+
+ async fn set(&self, key: SessionId, value: TxServer) {
+ let mut store = self.store.write().await;
+ store.insert(key, Arc::new(Mutex::new(value)));
+ }
+
+ async fn delete(&self, key: &SessionId) {
+ let mut store = self.store.write().await;
+ store.remove(key);
+ }
+
+ async fn clear(&self) {
+ let mut store = self.store.write().await;
+ store.clear();
+ }
+}
diff --git a/crates/rust-mcp-sdk/src/lib.rs b/crates/rust-mcp-sdk/src/lib.rs
index ab7965c..206b92c 100644
--- a/crates/rust-mcp-sdk/src/lib.rs
+++ b/crates/rust-mcp-sdk/src/lib.rs
@@ -1,4 +1,6 @@
pub mod error;
+#[cfg(feature = "hyper-server")]
+mod hyper_servers;
mod mcp_handlers;
mod mcp_macros;
mod mcp_runtimes;
@@ -17,8 +19,8 @@ pub mod mcp_client {
//! it works with `mcp_server_handler` trait
//! that offers default implementation for common messages like handling initialization or
//! responding to ping requests, so you only need to override and customize the handler
- //! functions relevant to your specific needs.
- //!
+ //! functions relevant to your specific needs.
+ //!
//! Refer to [examples/simple-mcp-client](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client) for an example.
//!
//!
@@ -48,8 +50,8 @@ pub mod mcp_server {
//! it works with `mcp_server_handler` trait
//! that offers default implementation for common messages like handling initialization or
//! responding to ping requests, so you only need to override and customize the handler
- //! functions relevant to your specific needs.
- //!
+ //! functions relevant to your specific needs.
+ //!
//! Refer to [examples/hello-world-mcp-server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server) for an example.
//!
//!
@@ -66,6 +68,13 @@ pub mod mcp_server {
pub use super::mcp_runtimes::server_runtime::mcp_server_runtime as server_runtime;
pub use super::mcp_runtimes::server_runtime::mcp_server_runtime_core as server_runtime_core;
pub use super::mcp_runtimes::server_runtime::ServerRuntime;
+
+ #[cfg(feature = "hyper-server")]
+ pub use super::hyper_servers::hyper_server;
+ #[cfg(feature = "hyper-server")]
+ pub use super::hyper_servers::hyper_server_core;
+ #[cfg(feature = "hyper-server")]
+ pub use super::hyper_servers::*;
}
#[cfg(feature = "client")]
diff --git a/crates/rust-mcp-sdk/src/mcp_runtimes/server_runtime.rs b/crates/rust-mcp-sdk/src/mcp_runtimes/server_runtime.rs
index b6828a6..d325305 100644
--- a/crates/rust-mcp-sdk/src/mcp_runtimes/server_runtime.rs
+++ b/crates/rust-mcp-sdk/src/mcp_runtimes/server_runtime.rs
@@ -12,6 +12,8 @@ use std::sync::{Arc, RwLock};
use tokio::io::AsyncWriteExt;
use crate::error::SdkResult;
+#[cfg(feature = "hyper-server")]
+use crate::hyper_servers::SessionId;
use crate::mcp_traits::mcp_handler::McpServerHandler;
use crate::mcp_traits::mcp_server::McpServer;
@@ -20,14 +22,16 @@ pub struct ServerRuntime {
// The transport interface for handling messages between client and server
transport: Box>,
// The handler for processing MCP messages
- handler: Box,
+ handler: Arc,
// Information about the server
- server_details: InitializeResult,
+ server_details: Arc,
// Details about the connected client
client_details: Arc>>,
message_sender: tokio::sync::RwLock