Skip to main content

StreamableHttpTransport

Struct StreamableHttpTransport 

Source
pub struct StreamableHttpTransport { /* private fields */ }
Available on crate feature mcp only.
Expand description

Streamable-HTTP MCP transport.

Construct with StreamableHttpTransport::new for a live connection, or StreamableHttpTransport::with_poster to inject a custom HttpPoster (used by tests).

Implementations§

Source§

impl StreamableHttpTransport

Source

pub fn new(endpoint: impl Into<String>, auth: McpAuth) -> Result<Arc<Self>>

Create a transport that talks to endpoint over real HTTP.

§Errors

Returns an error if the underlying HTTP client cannot be built.

Source

pub fn with_timeout( endpoint: impl Into<String>, auth: McpAuth, request_timeout: Duration, ) -> Result<Arc<Self>>

Create a transport over real HTTP with a custom per-request timeout.

Sets both the underlying reqwest client’s request timeout and the transport-level send deadline to request_timeout, so a slow or hung streamable-HTTP server trips this deadline instead of the DEFAULT_SEND_DEADLINE / DEFAULT_HTTP_TIMEOUT defaults. MCP tool calls routinely exceed 60s (builds, codegen); raise the timeout for those servers, or lower it for latency-sensitive ones.

§Errors

Returns an error if the underlying HTTP client cannot be built.

Source

pub fn with_poster(poster: Arc<dyn HttpPoster>, auth: McpAuth) -> Arc<Self>

Create a transport backed by a custom HttpPoster.

This is the seam tests use to script JSON / SSE responses without a network.

Source

pub fn builder(endpoint: impl Into<String>, auth: McpAuth) -> Result<Self>

Create an un-wrapped transport over real HTTP for further builder-style configuration (e.g. StreamableHttpTransport::with_header).

The backing reqwest client uses DEFAULT_HTTP_TIMEOUT and the transport uses DEFAULT_SEND_DEADLINE. To raise the request timeout past the default minute (e.g. for long builds / codegen), use StreamableHttpTransport::builder_with_timeout — calling StreamableHttpTransport::with_request_timeout on a builder produced here only relaxes the send deadline and cannot lift the client’s own DEFAULT_HTTP_TIMEOUT (see its docs).

Wrap the result in Arc before handing it to McpClient::new:

use std::sync::Arc;
use agent_sdk::mcp::{McpAuth, StreamableHttpTransport};

let transport = Arc::new(
    StreamableHttpTransport::builder("https://example.com/mcp", McpAuth::None)?
        .with_header("X-Tenant-Id", "acme"),
);
§Errors

Returns an error if the underlying HTTP client cannot be built.

Source

pub fn builder_with_timeout( endpoint: impl Into<String>, auth: McpAuth, request_timeout: Duration, ) -> Result<Self>

Create an un-wrapped transport over real HTTP with a custom request timeout, for further builder-style configuration before wrapping in Arc.

Sets both the backing reqwest client’s request timeout and the transport-level send deadline to request_timeout. This is the path to use when raising the timeout past DEFAULT_HTTP_TIMEOUT: building the client with the higher timeout is the only way a long-running tool call (build, codegen) can run past the default minute — chaining StreamableHttpTransport::with_request_timeout onto a plain StreamableHttpTransport::builder cannot, because the underlying reqwest client was already built with DEFAULT_HTTP_TIMEOUT.

Mirrors StreamableHttpTransport::with_timeout but returns an un-wrapped transport so callers can chain StreamableHttpTransport::with_header before wrapping in Arc:

use std::sync::Arc;
use std::time::Duration;
use agent_sdk::mcp::{McpAuth, StreamableHttpTransport};

let transport = Arc::new(
    StreamableHttpTransport::builder_with_timeout(
        "https://example.com/mcp",
        McpAuth::None,
        Duration::from_secs(300),
    )?
    .with_header("X-Tenant-Id", "acme"),
);
§Errors

Returns an error if the underlying HTTP client cannot be built.

Source

pub fn with_poster_owned(poster: Arc<dyn HttpPoster>, auth: McpAuth) -> Self

Create an un-wrapped transport backed by a custom HttpPoster, for further builder-style configuration before wrapping in Arc.

Source

pub fn with_header( self, name: impl Into<String>, value: impl Into<String>, ) -> Self

Add a static custom header sent on every request (e.g. a tenant id).

Call this on an un-wrapped transport from StreamableHttpTransport::builder (or StreamableHttpTransport::with_poster_owned) before wrapping it in Arc.

Source

pub fn with_request_timeout(self, request_timeout: Duration) -> Self

Set the overall per-request send deadline (default DEFAULT_SEND_DEADLINE).

This bounds every McpTransport::send / send_notification call regardless of the underlying HttpPoster’s own timeout, so a custom poster (or a ReqwestPoster whose client timeout is longer) still has a guaranteed cancellation path. Call it on an un-wrapped transport from StreamableHttpTransport::builder or StreamableHttpTransport::with_poster_owned before wrapping in Arc.

§This never raises the bound past the backing poster’s own timeout

The effective per-request bound is the minimum of this send deadline and the backing HttpPoster’s own timeout. For a ReqwestPoster built via StreamableHttpTransport::builder / ReqwestPoster::new, that client timeout is DEFAULT_HTTP_TIMEOUT (60s), so:

  • Lowering works: with_request_timeout(Duration::from_secs(5)) trips the send deadline at 5s, well before the client’s 60s.
  • Raising does not work here: with_request_timeout(Duration::from_secs(300)) leaves the send deadline at 300s but the client still aborts the request at its own 60s DEFAULT_HTTP_TIMEOUT. To genuinely raise the timeout, build the transport with StreamableHttpTransport::builder_with_timeout (or StreamableHttpTransport::with_timeout), which configures both the reqwest client timeout and this send deadline together.

Trait Implementations§

Source§

impl McpTransport for StreamableHttpTransport

Source§

fn send<'life0, 'async_trait>( &'life0 self, request: JsonRpcRequest, ) -> Pin<Box<dyn Future<Output = Result<JsonRpcResponse>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Send a request and wait for a response. Read more
Source§

fn send_notification<'life0, 'async_trait>( &'life0 self, request: JsonRpcRequest, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Send a notification (fire-and-forget, no response expected). Read more
Source§

fn set_protocol_version<'life0, 'life1, 'async_trait>( &'life0 self, version: &'life1 str, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Record the protocol revision negotiated during initialize. Read more
Source§

fn close<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Close the transport connection. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more