Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .release-plz.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ version_group = "acp"
# major release here. Keep it outside the `acp` version group because its
# version need not equal the core version, but verify dependency-only release
# proposals manually: core 1.x -> 2.x requires rmcp 2.x -> 3.x even if
# release-plz initially classifies the manifest update as a patch.
# release-plz initially classifies the manifest update as a patch. Upgrading
# the public rmcp dependency from 2.x -> 3.x similarly requires this integration
# crate to move from 3.x -> 4.x; it does not require a core ACP major release.
[[package]]
name = "agent-client-protocol-rmcp"

Expand Down
75 changes: 16 additions & 59 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }

# MCP SDK
rmcp = { version = "2.1.0", features = ["server", "transport-io", "schemars"] }
rmcp = { version = "3.4.0", features = ["server", "transport-io", "schemars"] }

# CLI parsing
clap = { version = "4.5", features = ["derive"] }
Expand Down
1 change: 1 addition & 0 deletions md/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

# Reference

- [Migrating the rmcp Integration to v4](./migration-rmcp-v4.md)
- [Migrating to v2.0](./migration_v2.0.md)
- [Migrating to v0.11](./migration_v0.11.x.md)

Expand Down
61 changes: 61 additions & 0 deletions md/migration-rmcp-v4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Migrating the rmcp Integration to v4

The next major release of `agent-client-protocol-rmcp` upgrades its public
`rmcp` dependency from 2.x to 3.4. This is a breaking change for integrations
that pass rmcp services or types across the crate boundary. The core
`agent-client-protocol` SDK remains on 2.x, and the minimum supported Rust
version remains 1.88.

| Integration crate | Core ACP SDK | MCP SDK |
| --- | --- | --- |
| `agent-client-protocol-rmcp` 4.x (unreleased) | 2.x | `rmcp` 3.x |
| `agent-client-protocol-rmcp` 3.x | 2.x | `rmcp` 2.x |

Upgrade the application's rmcp dependency together with the integration crate.
A service implementing rmcp 2.x's `Service` cannot be passed to the new
`McpServer::from_rmcp`, even when it provides the same tools.

## Custom services and tools

- Use `ServerConfig` and `ClientConfig` instead of the deprecated `ServerInfo`
and `ClientInfo` aliases.
- A manual `ServerHandler::call_tool` implementation now returns
`Result<CallToolResponse, ErrorData>`. Convert a completed `CallToolResult`
with `.into()`. The response enum also represents MRTR input-required
results and task-extension results; do not assume every response is a
completed tool result.
- Functions registered with rmcp's `#[tool]` macro can still return
`CallToolResult`. The ACP integration's `tool` and `tool_fn` builder APIs also
remain available, and their results become completed tool responses.
- `ToolExecution` and `Tool::with_execution` are no longer part of the tool
model. Do not add the old task-execution marker to tool definitions.

For example, a manual handler that previously returned
`Ok(CallToolResult::structured(value))` returns
`Ok(CallToolResult::structured(value).into())` under its new
`CallToolResponse` return type.

## Modern MCP is now available to supplied services

rmcp 3.4 implements discovery, per-request metadata, modern result shapes,
MRTR, and subscription APIs for MCP 2026-07-28. The adapter preserves those
requests and results when using `McpServer::from_rmcp`; a supplied service is
still responsible for its advertised capabilities and handlers.

The integration tests exercise both the built-in tool server and a supplied
rmcp service with actual 2026-07-28 requests, without sending `initialize`.
They cover direct tool calls before discovery, discovery itself, per-request
version errors, and an MRTR retry with fresh request metadata.

Do not treat the version-string constant or dependency upgrade alone as
protocol selection. rmcp 3.4's `ProtocolVersion::LATEST` still defaults to
2025-11-25. A modern client must select 2026-07-28 explicitly and include
the required request metadata.

## MCP-over-ACP remains a separate draft

This upgrade does not change ACP's unstable `mcp/connect`, `mcp/message`, or
`mcp/disconnect` envelopes. Redesigning that transport around stateless,
server-addressed requests is separate work. The new transport's latest-only
target does not require removing existing rmcp behavior from this prerequisite
dependency upgrade.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async fn test_scoped_mcp_server_through_proxy() -> Result<(), agent_client_proto
.await?;

expect_test::expect![[r#"
"OK: CallToolResult { content: [Text(TextContent { text: \"2\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"2\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"#]].assert_debug_eq(&result);

Ok(())
Expand Down Expand Up @@ -84,7 +84,7 @@ async fn test_scoped_mcp_server_through_session() -> Result<(), agent_client_pro
.await?;

expect_test::expect![[r#"
"OK: CallToolResult { content: [Text(TextContent { text: \"2\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"2\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"#]].assert_debug_eq(&result);

Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use agent_client_protocol::{
ByteStreams, ConnectTo, RunWithConnectionTo, mcp_server::McpServer, role::mcp, util::run_until,
};
use agent_client_protocol_rmcp::McpServerExt as _;
use rmcp::{ClientHandler, ServiceExt, model::ClientInfo};
use rmcp::{ClientHandler, ServiceExt, model::ClientConfig};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
Expand Down Expand Up @@ -64,8 +64,8 @@ fn create_test_server() -> McpServer<mcp::Client, impl RunWithConnectionTo<mcp::
struct MinimalClientHandler;

impl ClientHandler for MinimalClientHandler {
fn get_info(&self) -> ClientInfo {
ClientInfo::default()
fn get_info(&self) -> ClientConfig {
ClientConfig::default()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/agent-client-protocol-conductor/tests/test_tool_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async fn test_tool_fn_greet() -> Result<(), agent_client_protocol::Error> {
.await?;

expect_test::expect![[r#"
"OK: CallToolResult { content: [Text(TextContent { text: \"\\\"Hello, World!\\\"\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"\\\"Hello, World!\\\"\", meta: None, annotations: None })], structured_content: None, is_error: Some(false), meta: None }"
"#]].assert_debug_eq(&result);

Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ async fn test_trace_client_mcp_server() -> Result<(), agent_client_protocol::Err
"sessionUpdate": String("agent_message_chunk"),
"content": Object {
"type": String("text"),
"text": String("OK: CallToolResult { content: [Text(TextContent { text: \"{\\\"echoed\\\":\\\"Client echoes: Hello from client test!\\\",\\\"call_number\\\":1}\", meta: None, annotations: None })], structured_content: Some(Object {\"echoed\": String(\"Client echoes: Hello from client test!\"), \"call_number\": Number(1)}), is_error: Some(false), meta: None }"),
"text": String("OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"{\\\"echoed\\\":\\\"Client echoes: Hello from client test!\\\",\\\"call_number\\\":1}\", meta: None, annotations: None })], structured_content: Some(Object {\"echoed\": String(\"Client echoes: Hello from client test!\"), \"call_number\": Number(1)}), is_error: Some(false), meta: None }"),
},
"messageId": String("testy-message-end-turn-1"),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol::Error>
"capabilities": Object {},
"clientInfo": Object {
"name": String("rmcp"),
"version": String("2.2.0"),
"version": String("3.4.0"),
},
},
},
Expand All @@ -689,7 +689,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol::Error>
},
"serverInfo": Object {
"name": String("rmcp"),
"version": String("2.2.0"),
"version": String("3.4.0"),
},
"instructions": String("A simple test MCP server with an echo tool"),
},
Expand Down Expand Up @@ -761,7 +761,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol::Error>
"sessionUpdate": String("agent_message_chunk"),
"content": Object {
"type": String("text"),
"text": String("OK: CallToolResult { content: [Text(TextContent { text: \"{\\\"result\\\":\\\"Echo: Hello from trace test!\\\"}\", meta: None, annotations: None })], structured_content: Some(Object {\"result\": String(\"Echo: Hello from trace test!\")}), is_error: Some(false), meta: None }"),
"text": String("OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"{\\\"result\\\":\\\"Echo: Hello from trace test!\\\"}\", meta: None, annotations: None })], structured_content: Some(Object {\"result\": String(\"Echo: Hello from trace test!\")}), is_error: Some(false), meta: None }"),
},
"messageId": String("testy-message-end-turn-1"),
},
Expand Down Expand Up @@ -794,7 +794,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol::Error>
"sessionUpdate": String("agent_message_chunk"),
"content": Object {
"type": String("text"),
"text": String("OK: CallToolResult { content: [Text(TextContent { text: \"{\\\"result\\\":\\\"Echo: Hello from trace test!\\\"}\", meta: None, annotations: None })], structured_content: Some(Object {\"result\": String(\"Echo: Hello from trace test!\")}), is_error: Some(false), meta: None }"),
"text": String("OK: CallToolResult { result_type: None, content: [Text(TextContent { text: \"{\\\"result\\\":\\\"Echo: Hello from trace test!\\\"}\", meta: None, annotations: None })], structured_content: Some(Object {\"result\": String(\"Echo: Hello from trace test!\")}), is_error: Some(false), meta: None }"),
},
"messageId": String("testy-message-end-turn-1"),
},
Expand Down
4 changes: 2 additions & 2 deletions src/agent-client-protocol-cookbook/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,8 @@ pub mod global_mcp_server {
//!
//! #[tool_handler]
//! impl ServerHandler for MyMcpServer {
//! fn get_info(&self) -> ServerInfo {
//! ServerInfo::new(ServerCapabilities::builder().enable_tools().build())
//! fn get_info(&self) -> ServerConfig {
//! ServerConfig::new(ServerCapabilities::builder().enable_tools().build())
//! .with_protocol_version(ProtocolVersion::V_2024_11_05)
//! .with_server_info(Implementation::from_build_env())
//! }
Expand Down
16 changes: 16 additions & 0 deletions src/agent-client-protocol-rmcp/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Breaking changes

- Upgrade the public `rmcp` dependency from 2.x to 3.4. This requires the next
major release of `agent-client-protocol-rmcp` (4.x), while the core ACP SDK
remains on 2.x. Services supplied to `McpServer::from_rmcp` must use rmcp 3.x.
- Adapt tool handlers to rmcp's `CallToolResponse`, use `ServerConfig` in place
of the deprecated `ServerInfo` alias, and remove legacy tool-execution
metadata. See the [migration guide](https://agentclientprotocol.github.io/rust-sdk/migration-rmcp-v4.html).

### Added

- Integration coverage for MCP 2026-07-28 requests without initialization,
discovery, per-request metadata/version validation, and MRTR results from
caller-supplied rmcp services. This dependency upgrade does not replace the
current unstable MCP-over-ACP wire lifecycle.

## [3.1.1](https://github.com/agentclientprotocol/rust-sdk/compare/agent-client-protocol-rmcp-v3.1.0...agent-client-protocol-rmcp-v3.1.1) - 2026-09-18

### Other
Expand Down
7 changes: 7 additions & 0 deletions src/agent-client-protocol-rmcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ release of either dependency therefore requires a major release of this crate.

| agent-client-protocol-rmcp | agent-client-protocol | rmcp |
| -------------------------- | --------------------- | ---- |
| 4.x (unreleased) | 2.x | 3.x |
| 3.x | 2.x | 2.x |
| 2.x | 1.x | 2.x |
| 1.x | 1.x | 1.x |

See the [rmcp 4.x integration migration guide](https://agentclientprotocol.github.io/rust-sdk/migration-rmcp-v4.html)
for adapting services to rmcp 3.x. The minimum supported Rust version remains
1.88. The dependency upgrade does not itself change the unstable ACP transport
envelopes or require applications to use modern MCP instead of rmcp's default
protocol version.

## Related Crates

- **[agent-client-protocol](../agent-client-protocol/)** — Core ACP protocol types and traits
Expand Down
4 changes: 2 additions & 2 deletions src/agent-client-protocol-rmcp/examples/with_mcp_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ impl ExampleMcpServer {
#[allow(unknown_lints, clippy::unused_async_trait_impl)]
#[tool_handler]
impl ServerHandler for ExampleMcpServer {
fn get_info(&self) -> ServerInfo {
ServerInfo::new(ServerCapabilities::builder().enable_tools().build())
fn get_info(&self) -> ServerConfig {
ServerConfig::new(ServerCapabilities::builder().enable_tools().build())
.with_server_info(Implementation::new("example-mcp-server", "0.1.0"))
.with_protocol_version(ProtocolVersion::V_2024_11_05)
.with_instructions("A simple example MCP server with an echo tool")
Expand Down
Loading
Loading