Commit graph

464 commits

Author SHA1 Message Date
github-actions[bot]
020a38b6ad
chore: release v1.5.0 (#804)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-16 12:47:24 -04:00
jh-block
01a6666429
fix: treat resource metadata JSON parse failure as soft error (#810)
In fetch_resource_metadata_from_url, a JSON parse failure on the
response body caused a fatal AuthError::MetadataError, preventing
discover_metadata() from falling through to direct
.well-known/oauth-authorization-server discovery (Strategy B).

MCP servers that return HTTP 200 with non-JSON content (e.g. HTML)
at their base URL caused the OAuth flow to abort entirely, even
when the server had a valid .well-known/oauth-authorization-server
endpoint.

Return Ok(None) on parse failure, consistent with how HTTP errors
are already handled in the same function.
2026-04-16 12:16:19 -04:00
Dale Seo
3e56d52764
fix: include http_request_id in request-wise priming event IDs (#799)
* fix: include http_request_id in request-wise priming event IDs

* refactor: use Option::into_iter and usize::from for priming

* fix: retain event cache for completed request-wise channels

* fix: track completed_at for cache eviction and resume

* fix: log resume failures at warn level

* test: add completed_cache_ttl eviction test

* fix: return empty stream on failed resume

* test: add resume after completion test
2026-04-16 12:02:35 -04:00
WeekendsuperHero
6603c1ff15
fix(macros): respect local feature in #[prompt] macro — omit + Send bound (#803)
* refactor(prompt): update return type handling

* fix(prompt): add omit send and test
2026-04-14 09:56:19 -04:00
Dale Seo
c99903a67a
fix(http): drain SSE stream for connection reuse (#790)
* fix(http): reduce latency on subsequent StreamableHttp calls

* refactor: rely on stream drain for connection reuse

* refactor: clean up comments and naming

* fix: restore pool_max_idle_per_host(0) for Linux
2026-04-13 16:33:30 -04:00
Will Pfleger
ad3997268d
feat(transport): add constructors for non_exhaustive error types (#806)
AuthRequiredError, InsufficientScopeError, and DynamicTransportError
were marked #[non_exhaustive] in #715/#768 but don't have constructors
usable by external crates. Add new() for the error types and
from_parts() for DynamicTransportError (the existing new() requires a
Transport type parameter, making it unusable for test fixtures).

Fixes #805
2026-04-13 16:31:26 -04:00
dependabot[bot]
a743f15654
chore(deps): update which requirement from 7 to 8 (#807)
Updates the requirements on [which](https://github.com/harryfei/which-rs) to permit the latest version.
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/7.0.0...8.0.2)

---
updated-dependencies:
- dependency-name: which
  dependency-version: 8.0.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 16:10:42 -04:00
Dale Seo
a64be23152
feat: add 2025-11-25 protocol version support (#802) 2026-04-10 15:21:48 -04:00
github-actions[bot]
4628720f89
chore: release v1.4.0 (#779)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-10 10:40:38 -04:00
Anar Azadaliyev
65d2b29da5
fix(server): remove initialized notification gate to support Streamable HTTP (#788)
* fix(server): remove initialized notification gate to support Streamable HTTP

The server's init handshake loop fatally rejected any request arriving
before the `notifications/initialized` message. This breaks Streamable
HTTP clients where each JSON-RPC message is a separate POST with no
ordering guarantee — `tools/list` can easily arrive before `initialized`.

Remove the ~40-line wait loop and enter `serve_inner` immediately after
sending `InitializeResult`. The `initialized` notification is now
handled as a regular notification by the main service loop, matching the
TypeScript SDK behavior (validated in typescript-sdk#578).

Also remove the now-unreachable `ExpectedInitializedNotification` error
variant from `ServerInitializeError`.

Closes #783

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(server): keep ExpectedInitializedNotification as deprecated

Retain the variant for semver compatibility — removing it would be a
breaking change caught by cargo-semver-checks. Mark it deprecated with
a note that it is never constructed and will be removed in a future
major release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Anar Azadaliyev <anar.azadaliye@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 19:23:59 -04:00
Dale Seo
a7b570062e
fix: pass GIT_TOKEN to release-plz CLI (#798)
* fix: pass GIT_TOKEN to release-plz CLI

* fix: bump Node.js to 22 in CI for SDK compatibility
2026-04-09 18:59:41 -04:00
Dale Seo
8a8c036ccb
chore: update Rust toolchain to 1.92 (#797) 2026-04-09 14:09:59 -04:00
Alex Hancock
34d0bc6cd2
fix: upgrade rustc in actions (#796) 2026-04-08 21:35:34 -04:00
Eren Atas
45a4cc5316
feat: add Default and constructors to ServerSseMessage (#794)
* feat: add Default and constructors to ServerSseMessage

* fix: add tests, missing feature gates, small test issues
2026-04-08 16:39:16 -04:00
Matthew Zeng
5f432834a1
feat: add meta to elicitation results (#792) 2026-04-08 15:07:04 -04:00
Dale Seo
be321a4abe
feat(macros): auto-generate get_info and default router (#785)
* feat(macros): auto-generate get_info and default router

* docs: simplify examples and docs with new defaults

* feat(macros): add tool_router(server_handler) to elide separate #[tool_handler] impl

* docs: add Tools section to README and simplify calculator examples with server_handler
2026-04-08 15:06:26 -04:00
Dale Seo
5891b45162
refactor: unify IntoCallToolResult Result impls (#787) 2026-04-08 10:39:18 -04:00
Dale Seo
d98248ac22
ci: add --locked to release-plz install (#786) 2026-04-08 10:39:00 -04:00
Dale Seo
929441e443
fix: default session keep_alive to 5 minutes (#780) 2026-04-08 10:36:19 -04:00
Axel
cabf71aa74
feat(transport): add which_command for cross-platform executable resolution (#774)
* feat(transport): add which_command for cross-platform executable resolution

Adds a `which_command()` helper that resolves executable paths via the
`which` crate before constructing a `tokio::process::Command`. This fixes
Windows failures where `.cmd` shim scripts (e.g. `npx.cmd`) are not
found by `Command::new()` without a fully-qualified path.

Closes #456

* refactor(transport): move which_command behind opt-in feature flag

Address review feedback: the `which` dependency is now gated behind a
separate `which-command` feature flag instead of being bundled into
`transport-child-process`. Users on Linux/macOS who don't need
cross-platform executable resolution no longer pull in the extra crate.

Also fixes the doc example import path to use the re-exported
`rmcp::transport::which_command`.
2026-04-07 06:58:23 -04:00
jokemanfire
8e22aa2de2
fix(http): add host check (#764)
Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-01 19:28:56 -04:00
Adrián Romero
012210baae
fix: example clients_everything_stdio (#770)
* fix: example clients_everything_stdio

* Apply suggestion from @DaleSeo

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>

---------

Co-authored-by: Alex Hancock <alexhancock@block.xyz>
Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-04-01 19:02:31 -04:00
lif
cf6988ac7c
fix: exclude local feature from docs.rs build (#782)
The `local` feature relaxes Send+Sync bounds, which causes items
gated behind `cfg(not(feature = "local"))` to be excluded when
docs.rs builds with all-features. Replace `all-features = true`
with an explicit feature list that omits `local`.

Signed-off-by: majiayu000 <1835304752@qq.com>
2026-04-01 17:40:11 -04:00
Dale Seo
52c93e9508
ci: add semver check job and disable release-plz semver (#776) 2026-03-27 14:47:59 -04:00
Will Pfleger
b74f5ca35b
feat(auth): add StoredCredentials::new() constructor (#778)
StoredCredentials is #[non_exhaustive] but has no constructor, making
it impossible for external crates implementing CredentialStore to
construct instances without a serde roundtrip workaround. Add a new()
constructor matching the pattern used for other #[non_exhaustive]
types in this crate.

Fixes #777
2026-03-27 14:47:41 -04:00
github-actions[bot]
ac749e3ced
chore: release v1.3.0 (#747)
* chore: release v2.0.0

* chore: version 1.3.0

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-03-26 11:31:13 -04:00
Guy Lichtman
0b36a84f05
feat: add "theme" to Icon (#766)
* feat: add theme field to Icon

* fix: update IconThem crates/rmcp/src/model.rs (non_exhaustive)

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>

* fix: update IconThem crates/rmcp/src/model.rs (eq, hash)

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>

* fix: update docs with full descriptions of theme from mcp spec

---------

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-03-26 10:26:44 -04:00
Dale Seo
6a3b32d3ab
chore: add #[non_exhaustive] to remaining public structs (#768)
* chore: add #[non_exhaustive] to remaining public structs

* chore: add #[non_exhaustive] to remaining public types

* chore: enable exhaustive_structs/enums clippy lints

* test: add untagged ServerResult deserialization regression tests
2026-03-26 10:23:58 -04:00
Will Pfleger
ee1c63c53f
feat(transport): add Unix domain socket client for streamable HTTP (#749)
* feat(transport): add Unix domain socket client for streamable HTTP

MCP hosts in Kubernetes environments with Envoy sidecars need to route
HTTP through Unix domain sockets because DNS-based URIs only resolve
via the proxy. Adds UnixSocketHttpClient implementing StreamableHttpClient
using hyper over tokio::net::UnixStream, gated behind the
transport-streamable-http-client-unix-socket feature.

Also extracts RESERVED_HEADERS, extract_scope_from_header, and
validate_custom_header into common/http_header.rs to share header
validation logic between the reqwest and unix socket implementations.

* fix(transport): address review feedback for unix socket transport

- Document one-connection-per-request behavior on UnixSocketHttpClient
- Reject empty socket paths and bare '@' in constructor with assert
- Add explicit dep:http to unix-socket feature for self-documenting deps
- Document MCP-Protocol-Version exception on RESERVED_HEADERS constant
- Fix test catch-all to echo request id instead of hardcoding 1
- Remove leftover sleep(100ms) in test_unix_socket_custom_headers
- Add blank line before macro comment in Cargo.toml

* fix(transport): fix CI failures for unix socket transport

- Use std::io::Error::other() instead of Error::new(ErrorKind::Other)
  to satisfy clippy::io_other_error on newer nightly
- Use #[tokio::test(flavor = "current_thread")] for unix socket tests
  since axum's serve(UnixListener) requires spawn_local
- Gate validate_custom_header behind client-side-sse feature since it
  references http::HeaderName which isn't available with default features

* fix(transport): fix CI failures for unix socket transport

axum::serve(UnixListener) uses spawn_local on Linux, which panics
outside a LocalSet. Replace with manual hyper HTTP/1.1 server that
accepts connections directly from the UnixListener, avoiding the
spawn_local requirement entirely.

* fix(transport): skip unix socket tests when local feature is enabled

The local feature causes ().serve(transport) to use spawn_local, which
requires a LocalSet. Gate the integration tests with not(feature = "local")
to match every other integration test in the repo.
2026-03-24 09:50:32 -04:00
Wils Dawson
a32a9c83a1
feat(auth): implement SEP-2207 OIDC-flavored refresh token guidance (#676)
* feat: implement sep-2207 refresh token guidance

* fix: update client-metadata.json to allow refresh tokens
2026-03-23 20:15:23 -04:00
Guy Lichtman
baf22d37bb
chore: run all tests in ci without "local" feature (#761) 2026-03-23 19:03:16 -04:00
dependabot[bot]
f89e412200
chore(deps): update tokio-tungstenite requirement from 0.28.0 to 0.29.0 (#773)
Updates the requirements on [tokio-tungstenite](https://github.com/snapview/tokio-tungstenite) to permit the latest version.
- [Changelog](https://github.com/snapview/tokio-tungstenite/blob/master/CHANGELOG.md)
- [Commits](https://github.com/snapview/tokio-tungstenite/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: tokio-tungstenite
  dependency-version: 0.29.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 15:23:28 -04:00
Dale Seo
c8c0c0cffc
fix: prevent CallToolResult and GetTaskPayloadResult from shadowing CustomResult in untagged enums (#771)
The `#[serde(default)]` on `CallToolResult.content` (added in #752) made
all fields optional, causing `CallToolResult` to greedily match any JSON
object during `#[serde(untagged)]` deserialization of `ServerResult`.
Similarly, `GetTaskPayloadResult(Value)` matched everything before
`CustomResult(Value)` could be reached.

Fix by replacing derived `Deserialize` impls with custom ones:
- `CallToolResult`: require at least one known field to be present
- `GetTaskPayloadResult`: always fail (indistinguishable from
  `CustomResult` in JSON; construct programmatically via `::new()`)
2026-03-23 15:20:55 -04:00
jokemanfire
30cdc38c9a
chore: remove the rig example (#763)
The rig official has the mcp example, we need not to keep it just give the link.

Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn>
2026-03-23 09:01:49 +08:00
Guy Lichtman
3ea8c3c555
feat: add configuration for transparent session re-init (#760)
* feat: add configuration for transparent session re-init

* fix: in ci revert running tests without local until all tests pass

* fix: pr comments

* fix: documentation
2026-03-22 15:05:40 -04:00
Dale Seo
251ebec098
fix: drain in-flight responses on stdin EOF (#759) 2026-03-18 11:38:15 -04:00
Dale Seo
e709d0d084
fix: remove default type param from StreamableHttpService (#758) 2026-03-18 11:37:51 -04:00
Dale Seo
d485249048
fix: use cfg-gated Send+Sync supertraits to avoid semver break (#757) 2026-03-18 11:37:32 -04:00
Axel
55b478b0f4
fix(rmcp): surface JSON-RPC error bodies on HTTP 4xx responses (#748)
* fix(rmcp): surface JSON-RPC error bodies on HTTP 4xx responses

When a server returns a 4xx status with Content-Type: application/json,
attempt to deserialize the body as a ServerJsonRpcMessage before falling
back to UnexpectedServerResponse. This allows JSON-RPC error payloads
carried on HTTP error responses to be surfaced as McpError instead of
being lost in a transport-level error string.

Fixes #724

* fix(rmcp): surface JSON-RPC error bodies on HTTP 4xx responses

When a server returns a 4xx status with Content-Type: application/json,
attempt to deserialize the body as a ServerJsonRpcMessage before falling
back to UnexpectedServerResponse. This allows JSON-RPC error payloads
carried on HTTP error responses to be surfaced as McpError instead of
being lost in a transport-level error string.

Fixes #724

* fix(rmcp): only accept JsonRpcMessage::Error on non-success responses
2026-03-17 09:27:45 -04:00
Dale Seo
44dfcf5550
fix: default CallToolResult content to empty vec on missing field (#752) 2026-03-13 16:02:20 -04:00
Warwick
66712db808
fix(auth): redact secrets in Debug output for StoredCredentials and StoredAuthorizationState (#744)
* fix(auth): redact secrets in Debug output for StoredCredentials and StoredAuthorizationState

Removes `Debug` from the derive macros on `StoredCredentials` and
`StoredAuthorizationState` and replaces them with manual `Debug` impls
that print `[REDACTED]` for sensitive fields (access/refresh tokens,
PKCE verifiers, and CSRF tokens), preventing accidental credential
leakage via `{:?}` formatters, log calls, and error chains.

Fixes #741

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(auth): assert Debug output redacts secrets for credential types

Adds regression tests for the fix in the previous commit, verifying
that `{:?}` formatting of `StoredAuthorizationState` and
`StoredCredentials` does not emit plaintext secrets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(auth): address review feedback on debug redaction tests

- Remove redundant VendorExtraTokenFields from use super:: in
  test_stored_credentials_debug_redacts_token_response (already
  imported at module scope)
- Add assert!(debug_output.contains("created_at")) to
  test_stored_authorization_state_debug_redacts_secrets to verify
  non-secret fields remain visible in Debug output
- Run cargo fmt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update crates/rmcp/src/transport/auth.rs

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>

* fix: remaining formatting issue

* fix: formatting

* fix: formatting

* fix: please

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-03-13 15:51:02 -04:00
Dale Seo
1a4a52a173
feat: add local feature for !Send tool handler support (#740)
* feat: add local feature for !Send tool handler support

* fix: gate streamable HTTP transport on not(local) feature
2026-03-11 17:22:56 -04:00
Dale Seo
8700e5c920
chore: fix all clippy warnings across workspace (#746) 2026-03-11 14:12:00 -04:00
github-actions[bot]
3bd7522070
chore: release v1.2.0 (#736)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-11 10:28:11 -04:00
Dale Seo
27b00967f1
feat: transparent session re-init on HTTP 404 (#743) 2026-03-11 10:27:00 -04:00
Dale Seo
5322430772
fix: handle ping requests sent before initialize handshake (#745) 2026-03-11 10:09:10 -04:00
Dale Seo
3d2c951ca3
feat: add missing constructors for non-exhaustive model types (#739)
* feat: add constructors for Root and ListRootsResult

* feat: add constructors for UnsubscribeRequestParams and PromptReference
2026-03-10 13:13:53 -04:00
dependabot[bot]
656a09a97a
chore(deps): update rig-core requirement from 0.31.0 to 0.32.0 (#738)
Updates the requirements on [rig-core](https://github.com/0xPlaygrounds/rig) to permit the latest version.
- [Release notes](https://github.com/0xPlaygrounds/rig/releases)
- [Changelog](https://github.com/0xPlaygrounds/rig/blob/main/release-plz.toml)
- [Commits](https://github.com/0xPlaygrounds/rig/compare/rig-core-v0.31.0...rig-core-v0.32.0)

---
updated-dependencies:
- dependency-name: rig-core
  dependency-version: 0.32.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 16:41:38 -04:00
dependabot[bot]
9fbf91e021
chore(deps): update jsonwebtoken requirement from 9 to 10 (#737)
Updates the requirements on [jsonwebtoken](https://github.com/Keats/jsonwebtoken) to permit the latest version.
- [Changelog](https://github.com/Keats/jsonwebtoken/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Keats/jsonwebtoken/compare/v9.0.0...v10.3.0)

---
updated-dependencies:
- dependency-name: jsonwebtoken
  dependency-version: 10.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 16:41:16 -04:00
Dale Seo
54bb522e7f
feat: include granted scopes in OAuth refresh token request (#731)
* fix: include granted scopes in OAuth refresh token request

* docs: document scope forwarding in token refresh flow
2026-03-09 16:30:19 -04:00