Commit graph

520 commits

Author SHA1 Message Date
Dale Seo
e1af378949
chore: consolidate repeated rmcp tests (#931) 2026-06-26 16:15:20 -04:00
Dale Seo
4b9bea7e7d
Revert "feat!: relax tool result structuredContent type (#919)" (#932)
This reverts commit b8a936c4f5.
2026-06-26 16:00:02 -04:00
Dale Seo
b8a936c4f5
feat!: relax tool result structuredContent type (#919) 2026-06-26 14:57:18 -04:00
moroviintaas
415852806d
fix: fill missing fully qualified syntax in prompt_handler macros (#866)
* fix: fill missing fully qualified syntax in prompt_handler macros

* fix: remove unused prompt handler test imports

---------

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-06-26 12:38:17 -04:00
Dale Seo
d1cabb458f
feat: deprecate roots/sampling/logging types (#923) 2026-06-25 21:11:59 -04:00
Dale Seo
f07ee4ae1a
docs: align README examples with v2 model API (#928) 2026-06-25 20:00:51 -04:00
Dale Seo
f1daa9277e
docs: explain OAuth HTTP client setup (#918) 2026-06-25 19:59:47 -04:00
Dale Seo
77932141e3
feat!: align model types with MCP 2025-11-25 spec (#927)
* feat!: align model types with MCP 2025-11-25 spec

* fix: complete 2025-11-25 model spec conformance
2026-06-24 20:41:13 -04:00
Dale Seo
42a1069833
ci: add cargo-public-api check for breaking API changes (#924)
* chore: bump Rust toolchain to 1.96

* ci: add cargo-public-api breaking-change check

Adds a release-type-aware `cargo-public-api` diff job that fails on
changed/removed public items unless the PR's commits mark a breaking
(major) release. This catches source-breaking API changes that
cargo-semver-checks cannot yet detect (e.g. function return-type or
field-type changes).
2026-06-24 15:19:04 -04:00
Dale Seo
b79e0d9df3
ci: honor breaking semver markers (#922) 2026-06-23 17:53:57 -04:00
Brice Fernandes
0a95c3b608
fix(rmcp): add Audio variant to PromptMessageContent (#865)
The spec's prompt-message ContentBlock union is
`text | image | audio | resource_link | resource`, but
PromptMessageContent omitted `Audio`. Because the enum is
`#[serde(tag = "type")]` with no catch-all, a spec-conformant
`{"type":"audio",...}` content block failed to deserialize with
"unknown variant `audio`", breaking prompts/get for any server that
returns audio prompt content (the audio analogue of #842 / #843).

The supporting AudioContent type already existed, and Audio was
already a variant of the general RawContent enum (tool results,
sampling) -- only PromptMessageContent lacked it.

Add the flattened Audio variant (mirroring Image), a
PromptMessage::new_audio constructor (mirroring new_image), and
serialization + deserialization regression tests.

Fixes #864.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:35:40 -04:00
github-actions[bot]
25220361d5
chore: release v1.8.0 (#850)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-23 08:20:21 -04:00
Dale Seo
6d020c9684
fix(auth): preserve configured reqwest client (#917) 2026-06-22 17:34:16 -04:00
jif
de898dd842
Allow custom HTTP clients for OAuth (#908)
* feat: allow custom HTTP clients for OAuth

* fix(auth): preserve configured client for refresh

* fix(auth): harden OAuth HTTP adapter

* refactor(auth): simplify OAuth HTTP plumbing

* fix(auth): stop refresh token redirects by default

* fix(auth): re-export OAuth HTTP client types
2026-06-22 13:24:32 -04:00
King Star
3c5ce2b0d7
fix(auth): align OAuth metadata discovery ordering (#887) 2026-06-22 11:34:18 -04:00
Dale Seo
443677ca31
fix: align progress timeout token (#909) 2026-06-22 10:59:32 -04:00
Abdoul
4fd4986b62
fix(elicitation): preserve enumNames through ElicitationSchema serde round-trip (#905)
* fix(elicitation): preserve enumNames through ElicitationSchema serde round-trip

UntitledSingleSelectEnumSchema lacked deny_unknown_fields, so a legacy
enum payload containing enumNames was silently matched by that variant
(ignoring the field) rather than falling through to LegacyEnumSchema.
The enumNames array was lost on re-serialization.

Add deny_unknown_fields to UntitledSingleSelectEnumSchema so that any
unknown field (including enumNames) causes serde to try the next
untagged variant, reaching LegacyEnumSchema correctly.

Also add skip_serializing_if = "Option::is_none" to
LegacyEnumSchema::enum_names so that an untitled legacy enum without
enumNames does not serialize "enumNames": null.

Fixes #903

* test(elicitation): regenerate server schema snapshot for deny_unknown_fields

deny_unknown_fields on UntitledSingleSelectEnumSchema makes schemars
emit additionalProperties: false for that definition. Regenerate the
golden schema fixtures to match (UPDATE_SCHEMA=1 cargo test -p rmcp
--test test_message_schema --all-features).
2026-06-20 16:55:51 -04:00
dependabot[bot]
bf71eb8b09
chore(deps): bump actions/checkout from 6 to 7 (#911)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 06:59:25 -04:00
ContextVM-org
5d00e20f2a
Add progress-aware request timeout reset (#858)
* feat: add progress-aware request timeouts

* Update crates/rmcp/src/service.rs

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

* refactor(rmcp): move helpers and simplify response waiting

---------

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-06-17 15:07:37 -04:00
Greg Virgin
4b82e41522
docs(server): document Err vs Ok(CallToolResult::error) visibility contract on ServerHandler::call_tool (#854)
* docs(server): document Err vs Ok(CallToolResult::error) visibility contract

The MCP spec separates two failure modes that surface very differently in
clients:

  - Err(ErrorData) is a JSON-RPC protocol error. Most MCP clients render
    it opaquely ("Tool result missing due to internal error") - the
    caller does not see the message text.
  - Ok(CallToolResult::error(content)) is a tool-level error. Clients
    render the content; the caller reads the message.

The right shape for "the tool didn't work" is the latter, but Err is
what most handlers reach for because it looks like the natural Rust
return value. This commit adds rustdoc on both ServerHandler::call_tool
and CallToolResult::error pointing handlers at the correct shape, with
a worked example showing protocol errors (-32602 invalid_params) vs
tool errors (empty result, downstream failure).

This is the docs half of the visibility-contract ask. A follow-up may
introduce a typed ToolOutcome sum type to enforce the distinction at
compile time; this PR is the lower-risk version that unblocks the
class immediately.

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

* docs: update crates/rmcp/src/handler/server.rs

* docs: update crates/rmcp/src/model.rs

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-06-16 22:13:33 -04:00
Dale Seo
95a8e961e0
feat: standardize resource-not-found error code (SEP-2164) (#899)
* feat: implement SEP-2164 resource not found errors

* test: update protocol version utility expectations

* feat: gate not-found code at server boundary

---------

Co-authored-by: Michael Neale <michael.neale@gmail.com>
2026-06-16 21:55:25 -04:00
dependabot[bot]
8f5310b424
chore(deps): update tower-http requirement from 0.6 to 0.7 (#906)
Updates the requirements on [tower-http](https://github.com/tower-rs/tower-http) to permit the latest version.
- [Release notes](https://github.com/tower-rs/tower-http/releases)
- [Commits](https://github.com/tower-rs/tower-http/compare/tower-http-0.6.0...tower-http-0.7.0)

---
updated-dependencies:
- dependency-name: tower-http
  dependency-version: 0.7.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-06-15 21:15:14 -04:00
Loocor
266f870e69
docs: refine mcpmate listing copy (#885) 2026-06-11 10:51:57 -04:00
0xWeakSheep
5a78773faa
fix: return tool errors for invalid arguments (#894) 2026-06-11 10:18:02 -04:00
Michael Neale
53c6daadd9
fix(auth): apply offline_access to reauth paths (#897)
* fix(auth): apply offline_access to reauth paths

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

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

---------

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
2026-06-11 06:43:49 -04:00
Dawid Nowak
52e731bec6
fix: Small improvement to progress demo (#898)
Signed-off-by: Dawid Nowak <nowakd@gmail.com>
2026-06-10 19:28:33 -04:00
Dale Seo
2536a05992
fix: update peer info on duplicate initialize (#862) 2026-06-10 15:42:09 -04:00
Michael Neale
2d3d1879ad
feat: validate OAuth authorization response issuer (#896)
* feat: validate OAuth authorization response issuer

* fix: tighten issuer validation callbacks
2026-06-10 13:08:31 +10:00
Stefano Amorelli
f1ef2ec86c
feat: specify OIDC application_type during dynamic client registration (SEP-837) (#883)
* feat(auth): specify OIDC application_type during client registration

SEP-837 [1] requires an MCP client to specify an application_type during
OIDC Dynamic Client Registration. When it is omitted, OIDC servers
default the client to "web", which conflicts with the loopback redirect
URIs that CLI and desktop clients use, so the registration can be
rejected.

I make register_client always send an application_type. It defaults to
"native" to match the loopback redirect this SDK uses, and I added
OAuthClientConfig::with_application_type so web clients can opt in. Tests
cover the serialized request body and the config default. Implements [2].

[1]: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/basic/authorization.mdx#L395
[2]: https://github.com/modelcontextprotocol/rust-sdk/issues/880

Signed-off-by: Stefano Amorelli <stefano@amorelli.tech>

* chore(auth): declare application_type in client metadata document

I set application_type to "native" in the hosted client metadata
document so the URL-based client id flow and dynamic registration agree
on the client type that SEP-837 [1] expects.

[1]: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/basic/authorization.mdx#L395

Signed-off-by: Stefano Amorelli <stefano@amorelli.tech>

---------

Signed-off-by: Stefano Amorelli <stefano@amorelli.tech>
2026-06-04 10:53:18 -04:00
Rohit Ghumare
82b04a31f5
feat: deprecate roots, sampling, and logging (SEP-2577) (#884)
SEP-2577 deprecates the Roots, Sampling, and Logging features. The
deprecation is advisory: the features stay fully functional and there is
no wire-level change. Mark the corresponding Rust APIs as deprecated so
downstream users get compiler warnings and migration guidance.

- Forward attributes through the service `method!` macros and deprecate
  `Peer::create_message`, `Peer::list_roots`, `Peer::set_level`, and
  `Peer::notify_logging_message`.
- Forward per-field attributes through the capability `builder!` macro and
  deprecate the generated `enable_roots`, `enable_sampling`, and
  `enable_logging` builders, plus the hand-written
  `enable_roots_list_changed`, `enable_sampling_tools`, and
  `enable_sampling_context`.
- Document the deprecation on the capability types and fields, and in the
  README feature sections.
- Allow `deprecated` at the crate's own call sites so the build stays
  warning-clean, and refresh the message schema snapshots.
2026-06-04 08:43:39 -04:00
Dale Seo
254f04a764
fix: strip and validate tool outputSchema and inputSchema (#860)
* fix: remove unnecessary fields from tools' outputSchema

* fix: validate input schema root type per MCP spec
2026-06-02 12:01:33 -04:00
Datron
8f558d83be
docs: added jilebi-mcp to the list of built with rmcp (#861) 2026-05-29 11:31:44 -04:00
savanne-kham
6a7f10af51
fix(examples): accept stringified prompt argument values (#859) 2026-05-28 11:32:35 -04:00
Federico Poli
53e4410d99
fix: remove unnecessary fields from tools' inputSchema (#856) 2026-05-28 11:28:57 -04:00
Dale Seo
c330fede90
fix: reject init header/body version mismatch (#853) 2026-05-18 20:21:22 -04:00
Dale Seo
d328751dc9
fix: align protocol version negotiation (#855)
* fix: align protocol version negotiation

* ci: relax semver-checks to allow minor changes
2026-05-18 16:54:08 -04:00
Alex Hancock
cc66e3091e
fix: accept 200 with empty body in response to notifications in addition to 202 (#849) 2026-05-14 14:52:11 -04:00
github-actions[bot]
3529c3675f
chore: release v1.6.1 (#831)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-13 09:36:22 -04:00
Dale Seo
d695046ffa
fix: enable task support on counter long_task example (#838)
* fix: enable task support on counter long_task example

* ci: include example targets when testing example crates
2026-05-13 09:22:58 -04:00
Dale Seo
5ccdfc07be
feat: add task-based stdio examples (#839)
* feat: add task-based stdio examples

* docs: add Tasks section to Chinese README
2026-05-13 09:22:29 -04:00
Yutaka Nishimura
d83b1566d0
fix(rmcp): flatten Resource variant of PromptMessageContent (#843)
The Resource variant of PromptMessageContent was missing #[serde(flatten)],
causing the embedded resource content block to serialize as a double-nested
shape `{ "type": "resource", "resource": { "resource": {...} } }` instead of
the spec-compliant flat shape `{ "type": "resource", "resource": {uri, mimeType, text} }`.

This caused Zod-based MCP clients (e.g. Claude Code) to reject prompts/get
responses containing embedded resource messages with InvalidUnion errors.

The Image and ResourceLink variants already use #[serde(flatten)] correctly;
only Resource was missing it.

Fix: add #[serde(flatten)] so EmbeddedResource (=Annotated<RawEmbeddedResource>)
fields _meta / annotations / resource are flattened to the content-block level,
matching the MCP spec for prompts embedded resources.

Regression test: test_prompt_message_resource_serialization_is_flat verifies
content.resource.uri is reachable and content.resource.resource is absent.

Schema snapshots regenerated via UPDATE_SCHEMA=1.
2026-05-12 14:46:12 -04:00
Dale Seo
321ab14f67
fix: reply -32700 on stdio parse errors instead of closing (#833)
* fix: reply -32700 on stdio parse errors instead of closing

* fix: make JsonRpcError id optional per MCP spec
2026-05-07 12:27:15 -04:00
Xuntao Chi
0f776ab1d6
chore(rmcp): remove dependency on chrono default features (#829) 2026-05-06 14:53:22 -04:00
Dale Seo
3bf5298972
ci: extend semver check to all features except local (#832) 2026-05-04 20:44:16 -04:00
dependabot[bot]
88df9af9f2
chore(deps): update askama requirement from 0.15 to 0.16 (#830)
Updates the requirements on [askama](https://github.com/askama-rs/askama) to permit the latest version.
- [Release notes](https://github.com/askama-rs/askama/releases)
- [Commits](https://github.com/askama-rs/askama/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: askama
  dependency-version: 0.16.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-05-04 20:37:16 -04:00
lutz-grex
2f8d3b7355
Fix/issue 817 idle timeout log level (#824)
* fix(transport): downgrade idle timeout log from error to debug

Idle keep-alive timeout is normal zombie-session cleanup, not a transport failure.

Route it through a dedicated WorkerQuitReason::IdleTimeout variant.

Log it at debug level instead of treating it as a fatal error.

Remove the unused LocalSessionWorkerError::KeepAliveTimeout variant.

Closes #817

* fix(session): tolerate dead worker in close_session

Swallow SessionServiceTerminated in close_session when the worker has already exited.
This prevents a spurious ERROR log during the post-exit cleanup path in
spawn_session_worker.

* fix(transport): address PR review feedback

- deprecate KeepAliveTimeout
- harden tests
2026-05-04 20:14:06 -04:00
github-actions[bot]
014fb2e6cd
chore: release v1.6.0 (#818)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-01 09:38:25 -04:00
Dale Seo
c1e0eadd5d
fix: add init_timeout for streamable-http sessions (#811) 2026-05-01 09:20:50 -04:00
Dale Seo
ef74147113
fix(http): fall back to :authority for HTTP/2 (#827) 2026-05-01 09:17:06 -04:00
Dale Seo
4cf78736e7
feat(http): log Host/Origin rejections (#826) 2026-05-01 14:42:47 +02:00