Skip to content

chore(deps): bump reqwest to 0.13.3 and rmcp to 1.5#3217

Open
laststylebender14 wants to merge 9 commits intomainfrom
chore/bump-reqwest-crate
Open

chore(deps): bump reqwest to 0.13.3 and rmcp to 1.5#3217
laststylebender14 wants to merge 9 commits intomainfrom
chore/bump-reqwest-crate

Conversation

@laststylebender14
Copy link
Copy Markdown
Contributor

@laststylebender14 laststylebender14 commented Apr 30, 2026

Summary

Bump reqwest from 0.12.23 to 0.13.3 and rmcp from 0.10 to 1.5, with a new forge_reqwest crate that centralizes reqwest::Client construction so all callers share a single TLS-roots configuration and avoid a startup-time regression introduced by reqwest 0.13.

Context

Bumping reqwest to 0.13 is non-trivial because 0.13 is a breaking release and several transitive dependencies needed to move with it:

  • rmcp 0.10 only supports reqwest 0.12 — keeping it would have pinned us back. Bumped to rmcp 1.5, which forced API migrations (renames, non-exhaustive constructors, removal of SseClientTransport).
  • oauth2's reqwest feature transitively pulls reqwest 0.12.x into the build, which conflicts with the workspace 0.13. We don't use that feature (we pass our own http_fn callback), so it's safe to drop.
  • forge_eventsource had a pinned reqwest 0.12.0 dep so its RequestBuilderExt::eventsource() was implemented for a different RequestBuilder type than forge_infra was calling — switched to the workspace reqwest so the trait resolves on the same type.

The most consequential change is a cold-start performance regression in reqwest 0.13. Per the upstream v0.13.0 changelog:

rustls roots features removed, rustls-platform-verifier is used by default.
To use different roots, call tls_certs_only(your_roots).

rustls-platform-verifier::Verifier::new() synchronously parses the OS trust store (/etc/ssl/certs/ca-certificates.crt on Linux) on every Client::build(). We measured this at ~38 ms on Linux CI via timing instrumentation. Three call sites built reqwest::Client eagerly during startup of commands like forge zsh rprompt (which never makes HTTP calls), pushing the benchmark from ~14 ms (main) to ~104 ms. CI threshold is 60 ms.

Changes

Dependency bumps

  • Workspace reqwest 0.12.23 → 0.13.3. Feature rustls-tlsrustls (renamed in 0.13).
  • Workspace rmcp 0.10.0 → 1.5; dropped transport-sse-client-reqwest (removed upstream).
  • forge_eventsource: now uses workspace reqwest.
  • forge_infra, forge_services: dropped oauth2's reqwest feature (we use http_fn callback).

New crate forge_reqwest

crates/forge_reqwest/src/lib.rs:18 — single helper:

pub fn builder() -> reqwest::ClientBuilder {
    reqwest::Client::builder().tls_certs_only(webpki_root_certs())
}

Returns a ClientBuilder preconfigured with the bundled Mozilla webpki root CAs (via the webpki-root-certs crate). This is the upstream-recommended replacement for the removed rustls-tls-webpki-roots feature and bypasses rustls-platform-verifier on Client::build().

A new crate (rather than an existing one) was needed because forge_infra already depends on forge_services, so forge_services::ForgeFetch cannot import from forge_infra without creating a cycle. forge_reqwest is a leaf crate that all three callers (forge_infra, forge_services, forge_tracker) can depend on.

Three reqwest::Client construction sites unified

File Change
crates/forge_infra/src/http.rs ForgeHttpInfra: OnceLock<Client> + forge_reqwest::builder()
crates/forge_services/src/tool_services/fetch.rs ForgeFetch: OnceLock<Client> + forge_reqwest::builder()
crates/forge_tracker/src/collect/posthog.rs posthog::Tracker: OnceLock<Client> + forge_reqwest::builder()

The OnceLock wrapper defers the (now cheaper) Client::build() to first HTTP use, keeping pure-Rust startup paths free of any HTTP construction.

rmcp 1.5 API migrations in crates/forge_infra/src/mcp_client.rs

  • CallToolRequestParamCallToolRequestParams; InitializeRequestParamInitializeRequestParams.
  • SseClientTransport removed upstream — HTTP fallback now uses StreamableHttpClientTransport only.
  • Non-exhaustive struct constructors: ClientInfo::new, CallToolRequestParams::new, StoredCredentials::new.
  • crates/forge_infra/src/auth/mcp_token_storage.rs: OAuthTokenResponse now uses VendorExtraTokenFields.

Behavior note

The MCP HTTP→SSE auto-fallback is gone (rmcp 1.x removed SseClientTransport); MCP servers requiring pure-SSE without streamable-HTTP support will no longer fall back automatically. This is the cost of moving to rmcp 1.5 (required for reqwest 0.13).

Cold-start perf timeline

forge zsh rprompt benchmark (CI Linux, threshold 60 ms):

State avg
main (reqwest 0.12) ~14 ms
Naive reqwest 0.13 bump (eager Client::build in 3 places) 104 ms
ForgeFetch lazy 94 ms
ForgeHttpInfra lazy too 62 ms
All 3 lazy + tls_certs_only(webpki) via forge_reqwest ~14 ms

Testing

# Build clean
cargo check
cargo clippy --all-targets

# All tests pass
cargo test --workspace

# Local cold-start benchmark
cargo build
for i in 1 2 3 4 5; do { time ./target/debug/forge zsh rprompt > /dev/null ; } 2>&1 | grep total; done

CI runs the perf benchmark under Performance / zsh rprompt with a 60 ms threshold.

Links

@github-actions github-actions Bot added the type: chore Routine tasks like conversions, reorganization, and maintenance work. label Apr 30, 2026
@laststylebender14 laststylebender14 changed the title chore(deps): bump reqwest to v0.13.3 chore(deps): bump reqwest to 0.13.3 and rmcp to 1.5 Apr 30, 2026
@laststylebender14 laststylebender14 force-pushed the chore/bump-reqwest-crate branch 8 times, most recently from 06682db to 5660399 Compare April 30, 2026 10:39
@laststylebender14 laststylebender14 marked this pull request as ready for review April 30, 2026 10:53
@amitksingh1490
Copy link
Copy Markdown
Contributor

perfromance degrade
%B%F{240}󱙺 FORGE%f%b %F{240}MEDIUM%f
⏱️ Running 10 iterations...

1 54 ms
2 55 ms
3 55 ms
4 55 ms
5 56 ms
6 56 ms
7 55 ms
8 55 ms
9 55 ms
10 56 ms

📊 Summary

avg 55 ms
min 54 ms
max 56 ms
on main its 13ms

@laststylebender14 laststylebender14 marked this pull request as draft April 30, 2026 11:03
@laststylebender14 laststylebender14 force-pushed the chore/bump-reqwest-crate branch 6 times, most recently from 6cb5f4b to 8f13766 Compare April 30, 2026 11:51
@laststylebender14 laststylebender14 marked this pull request as ready for review April 30, 2026 12:30
@laststylebender14 laststylebender14 marked this pull request as draft April 30, 2026 12:30
@laststylebender14 laststylebender14 force-pushed the chore/bump-reqwest-crate branch from 8f13766 to 3a01662 Compare April 30, 2026 12:36
- Workspace reqwest 0.12 -> 0.13.3 (rustls-tls -> rustls feature rename)
- rmcp 0.10 -> 1.5; drop transport-sse-client-reqwest feature (removed upstream)
- forge_eventsource: align with workspace reqwest so RequestBuilderExt::eventsource() resolves
- Drop oauth2 reqwest feature in forge_infra/forge_services (we use http_fn callback)
- rmcp 1.5 API migrations (param renames, non-exhaustive constructors,
  StreamableHttpClientTransport-only HTTP fallback)
- mcp_token_storage.rs: OAuthTokenResponse now uses VendorExtraTokenFields

New crate forge_reqwest (crates/forge_reqwest):

reqwest 0.13's rustls feature switched its default trust source to
rustls-platform-verifier, which synchronously parses the OS trust store
on every Client::build() (~38 ms on Linux). Per the upstream 0.13.0
changelog, the recommended replacement is to call tls_certs_only(roots).

forge_reqwest centralizes this:

    pub fn forge_reqwest::builder() -> reqwest::ClientBuilder

Returns a ClientBuilder preconfigured with bundled Mozilla webpki root
CAs, bypassing rustls-platform-verifier. All three reqwest::Client
construction sites use it:

* crates/forge_infra/src/http.rs                   (ForgeHttpInfra)
* crates/forge_services/src/tool_services/fetch.rs (ForgeFetch)
* crates/forge_tracker/src/collect/posthog.rs      (posthog::Tracker)

Each is also wrapped in OnceLock<Client> so Client::build() runs lazily
on first HTTP use, keeping cold-start commands like 'forge zsh rprompt'
fast.

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
@laststylebender14 laststylebender14 force-pushed the chore/bump-reqwest-crate branch from 3a01662 to 7b5adc4 Compare April 30, 2026 12:41
@laststylebender14 laststylebender14 marked this pull request as ready for review April 30, 2026 13:10
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions Bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. type: chore Routine tasks like conversions, reorganization, and maintenance work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants