Skip to content

Commit 6d2181e

Browse files
committed
Merge remote-tracking branch 'upstream/main'
# Conflicts: # crates/rmcp/CHANGELOG.md
2 parents a3c21ba + bdf0c32 commit 6d2181e

23 files changed

Lines changed: 1415 additions & 80 deletions

.github/workflows/conformance.yml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Conformance
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
concurrency:
11+
group: conformance-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
env:
15+
# Pinned for reproducible runs; bump deliberately when the suite updates.
16+
CONFORMANCE_VERSION: "0.1.16"
17+
18+
jobs:
19+
server:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
steps:
24+
- uses: actions/checkout@v7
25+
26+
- name: Install Rust toolchain
27+
uses: dtolnay/rust-toolchain@stable
28+
29+
- uses: Swatinem/rust-cache@v2
30+
31+
# Build the whole package (server + client bins): the conformance crate is
32+
# excluded from the workspace default-members, so this is the only CI job
33+
# that catches compile breakage in it.
34+
- name: Build conformance binaries
35+
run: cargo build -p mcp-conformance
36+
37+
- name: Start conformance server
38+
run: |
39+
PORT=8001 ./target/debug/conformance-server &
40+
echo $! > server.pid
41+
for _ in $(seq 1 30); do
42+
if curl -s -o /dev/null http://127.0.0.1:8001/mcp; then
43+
exit 0
44+
fi
45+
sleep 1
46+
done
47+
echo "conformance server did not become ready" >&2
48+
exit 1
49+
50+
- name: Run server conformance suite
51+
run: |
52+
npx -y "@modelcontextprotocol/conformance@${CONFORMANCE_VERSION}" server \
53+
--url http://127.0.0.1:8001/mcp \
54+
--spec-version 2025-11-25 \
55+
-o conformance-results
56+
57+
# These pass today but are excluded from the default "active" suite;
58+
# run them explicitly so regressions are still caught.
59+
- name: Run pending scenarios
60+
run: |
61+
for scenario in json-schema-2020-12 server-sse-polling; do
62+
npx -y "@modelcontextprotocol/conformance@${CONFORMANCE_VERSION}" server \
63+
--url http://127.0.0.1:8001/mcp \
64+
--scenario "$scenario" \
65+
-o conformance-results
66+
done
67+
68+
- name: Stop conformance server
69+
if: always()
70+
run: kill "$(cat server.pid)" 2>/dev/null || true
71+
72+
- name: Upload results
73+
if: always()
74+
uses: actions/upload-artifact@v7
75+
with:
76+
name: conformance-server-results
77+
path: conformance-results

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ default-members = ["crates/rmcp", "crates/rmcp-macros"]
44
resolver = "2"
55

66
[workspace.dependencies]
7-
rmcp = { version = "1.8.0", path = "./crates/rmcp" }
8-
rmcp-macros = { version = "1.8.0", path = "./crates/rmcp-macros" }
7+
rmcp = { version = "2.1.0", path = "./crates/rmcp" }
8+
rmcp-macros = { version = "2.1.0", path = "./crates/rmcp-macros" }
99

1010
[workspace.package]
1111
edition = "2024"
12-
version = "1.8.0"
12+
version = "2.1.0"
1313
authors = ["4t145 <u4t145@163.com>"]
1414
license = "Apache-2.0"
1515
repository = "https://github.com/modelcontextprotocol/rust-sdk/"

conformance/src/bin/server.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -656,11 +656,11 @@ impl ServerHandler for ConformanceServer {
656656
"test_prompt_with_arguments",
657657
Some("A test prompt that accepts arguments"),
658658
Some(vec![
659-
PromptArgument::new("name")
660-
.with_description("The name to greet")
659+
PromptArgument::new("arg1")
660+
.with_description("First test argument")
661661
.with_required(true),
662-
PromptArgument::new("style")
663-
.with_description("The greeting style")
662+
PromptArgument::new("arg2")
663+
.with_description("Second test argument")
664664
.with_required(false),
665665
]),
666666
),
@@ -692,14 +692,11 @@ impl ServerHandler for ConformanceServer {
692692
.with_description("A simple test prompt")),
693693
"test_prompt_with_arguments" => {
694694
let args = request.arguments.unwrap_or_default();
695-
let name = args.get("name").and_then(|v| v.as_str()).unwrap_or("World");
696-
let style = args
697-
.get("style")
698-
.and_then(|v| v.as_str())
699-
.unwrap_or("friendly");
695+
let arg1 = args.get("arg1").and_then(|v| v.as_str()).unwrap_or("");
696+
let arg2 = args.get("arg2").and_then(|v| v.as_str()).unwrap_or("");
700697
Ok(GetPromptResult::new(vec![PromptMessage::new_text(
701698
Role::User,
702-
format!("Please greet {} in a {} style.", name, style),
699+
format!("Prompt with arguments: arg1='{}', arg2='{}'", arg1, arg2),
703700
)])
704701
.with_description("A prompt with arguments"))
705702
}

crates/rmcp-macros/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [2.0.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-macros-v1.8.0...rmcp-macros-v2.0.0) - 2026-06-27
11+
12+
### Added
13+
14+
- [**breaking**] align model types with MCP 2025-11-25 spec ([#927](https://github.com/modelcontextprotocol/rust-sdk/pull/927))
15+
16+
### Fixed
17+
18+
- fill missing fully qualified syntax in prompt_handler macros ([#866](https://github.com/modelcontextprotocol/rust-sdk/pull/866))
19+
20+
### Other
21+
22+
- align README examples with v2 model API ([#928](https://github.com/modelcontextprotocol/rust-sdk/pull/928))
23+
1024
## [1.8.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-macros-v1.7.0...rmcp-macros-v1.8.0) - 2026-06-22
1125

1226
### Added

crates/rmcp/CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- *(server)* Normalise bare boolean subschemas (`true` / `false`) in generated `inputSchema`, `outputSchema`, and `ElicitationSchema` to their object-form equivalents (`{}` / `{"not": {}}`) before serialisation. Triggered by `serde_json::Value` field expansions, `Vec<serde_json::Value>`, `BTreeMap<String, serde_json::Value>`, and `#[serde(deny_unknown_fields)]`. Claude Code's `LocalMcpServerManager` schema walker throws `TypeError: Cannot use 'in' operator to search for 'properties' in <bool>` on bare booleans, silently dropping the entire server's tool list ([anthropics/claude-code#50194](https://github.com/anthropics/claude-code/issues/50194), [#25081](https://github.com/anthropics/claude-code/issues/25081)). The fix is unconditional — boolean subschemas are spec-legal per JSON Schema 2020-12 §4.3.2, but real-world MCP clients can't always handle them, so emit object form universally.
1313

14+
## [2.1.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v2.0.0...rmcp-v2.1.0) - 2026-07-02
15+
16+
### Added
17+
18+
- add SEP-414 trace context meta accessors ([#910](https://github.com/modelcontextprotocol/rust-sdk/pull/910))
19+
- add SEP-2575 meta helpers ([#942](https://github.com/modelcontextprotocol/rust-sdk/pull/942))
20+
21+
### Fixed
22+
23+
- *(transport)* make AsyncRwTransport::receive cancel-safe ([#941](https://github.com/modelcontextprotocol/rust-sdk/pull/941)) ([#947](https://github.com/modelcontextprotocol/rust-sdk/pull/947))
24+
- *(auth)* preserve refresh_token when refresh response omits it ([#949](https://github.com/modelcontextprotocol/rust-sdk/pull/949))
25+
- block redirect header leaks ([#936](https://github.com/modelcontextprotocol/rust-sdk/pull/936))
26+
- don't respond to unparsable messages ([#940](https://github.com/modelcontextprotocol/rust-sdk/pull/940))
27+
- negotiate protocol version in handler ([#930](https://github.com/modelcontextprotocol/rust-sdk/pull/930))
28+
29+
## [2.0.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v1.8.0...rmcp-v2.0.0) - 2026-06-27
30+
31+
### Added
32+
33+
- [**breaking**] relax tool result structuredContent type ([#919](https://github.com/modelcontextprotocol/rust-sdk/pull/919))
34+
- deprecate roots/sampling/logging types ([#923](https://github.com/modelcontextprotocol/rust-sdk/pull/923))
35+
- [**breaking**] align model types with MCP 2025-11-25 spec ([#927](https://github.com/modelcontextprotocol/rust-sdk/pull/927))
36+
37+
### Fixed
38+
39+
- prevent OAuth resource spoofing ([#937](https://github.com/modelcontextprotocol/rust-sdk/pull/937))
40+
- block oauth metadata ssrf ([#935](https://github.com/modelcontextprotocol/rust-sdk/pull/935))
41+
- prevent streamable HTTP session leak ([#934](https://github.com/modelcontextprotocol/rust-sdk/pull/934))
42+
- fill missing fully qualified syntax in prompt_handler macros ([#866](https://github.com/modelcontextprotocol/rust-sdk/pull/866))
43+
- *(rmcp)* add Audio variant to PromptMessageContent ([#865](https://github.com/modelcontextprotocol/rust-sdk/pull/865))
44+
45+
### Other
46+
47+
- consolidate repeated rmcp tests ([#931](https://github.com/modelcontextprotocol/rust-sdk/pull/931))
48+
- Revert "feat!: relax tool result structuredContent type ([#919](https://github.com/modelcontextprotocol/rust-sdk/pull/919))" ([#932](https://github.com/modelcontextprotocol/rust-sdk/pull/932))
49+
- align README examples with v2 model API ([#928](https://github.com/modelcontextprotocol/rust-sdk/pull/928))
50+
1451
## [1.8.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v1.7.0...rmcp-v1.8.0) - 2026-06-22
1552

1653
### Added

crates/rmcp/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,16 @@ name = "test_streamable_http_protocol_version"
286286
required-features = ["server", "client", "transport-streamable-http-server", "reqwest"]
287287
path = "tests/test_streamable_http_protocol_version.rs"
288288

289+
[[test]]
290+
name = "test_stateless_protocol_version"
291+
required-features = ["server", "transport-streamable-http-server", "reqwest"]
292+
path = "tests/test_stateless_protocol_version.rs"
293+
294+
[[test]]
295+
name = "test_protocol_version_negotiation"
296+
required-features = ["server", "client"]
297+
path = "tests/test_protocol_version_negotiation.rs"
298+
289299
[[test]]
290300
name = "test_streamable_http_4xx_error_body"
291301
required-features = ["transport-streamable-http-client", "transport-streamable-http-client-reqwest"]
@@ -297,6 +307,11 @@ name = "test_custom_request"
297307
required-features = ["server", "client"]
298308
path = "tests/test_custom_request.rs"
299309

310+
[[test]]
311+
name = "test_trace_context"
312+
required-features = ["server", "client"]
313+
path = "tests/test_trace_context.rs"
314+
300315
[[test]]
301316
name = "test_prompt_macros"
302317
required-features = ["server", "client"]

crates/rmcp/src/handler/server.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
model::{TaskSupport, *},
88
service::{
99
MaybeSendFuture, NotificationContext, RequestContext, RoleServer, Service, ServiceRole,
10+
negotiate_protocol_version,
1011
},
1112
};
1213

@@ -202,8 +203,13 @@ macro_rules! server_handler_methods {
202203
request: InitializeRequestParams,
203204
context: RequestContext<RoleServer>,
204205
) -> impl Future<Output = Result<InitializeResult, McpError>> + MaybeSendFuture + '_ {
205-
context.peer.set_peer_info(request);
206-
std::future::ready(Ok(self.get_info()))
206+
context.peer.set_peer_info(request.clone());
207+
let mut info = self.get_info();
208+
info.protocol_version = negotiate_protocol_version(
209+
&request.protocol_version,
210+
info.protocol_version,
211+
);
212+
std::future::ready(Ok(info))
207213
}
208214
fn complete(
209215
&self,

crates/rmcp/src/model/content.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ impl ContentBlock {
297297
ContentBlock::Resource(EmbeddedResource::new(
298298
ResourceContents::TextResourceContents {
299299
uri: uri.into(),
300-
mime_type: Some("text".to_string()),
300+
mime_type: Some("text/plain".to_string()),
301301
text: content.into(),
302302
meta: None,
303303
},

0 commit comments

Comments
 (0)