Skip to content

feat!: Add support for multiple active schema versions #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@ features = ["2025_03_26", "schema_utils"]
[features]

# defalt features
default = ["2025_03_26", "schema_utils"] # Default features
default = ["latest", "schema_utils"] # Default features

# activates the latest MCP schema version, this will be updated once a new version of schema is published
latest = ["2025_03_26"]

# enabled mcp schema version 2025_03_26
2025_03_26 = []
2025_03_26 = ["latest"]
# enabled mcp schema version 2024_11_05
2024_11_05 = []
# enabled draft mcp schema
Expand Down
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,30 +76,29 @@ This repository provides all official released versions the schema , including d

### How to switch between different schema versions?

By default, the latest version of the MCP Protocol schema is enabled.

Each schema version has a corresponding Cargo feature that can be enabled in your project's Cargo.toml.
By default, the version `2025_03_26` of the schema is active.

Multiple schema versions may be enabled concurrently if needed. Non-default versions are available under explicitly named modules, for example:

- rust_mcp_schema::mcp_2024_11_05
- rust_mcp_schema::mcp_draft"

Example: enable `2024_11_05` version of the shema:

<!-- x-release-please-start-version -->

```toml
# Cargo.toml
rust-mcp-schema = { version: 0.5.2 , features=["2024_11_05"] }
```

Example: enable `latest` version of the shema:

```toml
#Cargo.toml
rust-mcp-schema = { version: 0.5.2 , features=["latest"] }
rust-mcp-schema = { version: 0.5.2 , default-features = false, features=["2024_11_05"] }
```

Example: enable `draft`` version of the shema (2024_11_05) :

```toml
#Cargo.toml
rust-mcp-schema = { version: 0.5.2 , features=["draft"] }
rust-mcp-schema = { version: 0.5.2 , default-features = false, features=["draft"] }
```

<!-- x-release-please-end -->
Expand Down
13 changes: 13 additions & 0 deletions examples/mcp_client_handle_message.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#[cfg(feature = "latest")]
use rust_mcp_schema::schema_utils::*;
#[cfg(feature = "latest")]
use rust_mcp_schema::*;

#[cfg(feature = "2024_11_05")]
use rust_mcp_schema::mcp_2024_11_05::schema_utils::*;
#[cfg(feature = "2024_11_05")]
use rust_mcp_schema::mcp_2024_11_05::*;

#[cfg(feature = "draft")]
use rust_mcp_schema::mcp_draft::schema_utils::*;
#[cfg(feature = "draft")]
use rust_mcp_schema::mcp_draft::*;

use std::str::FromStr;

type AppError = RpcError;
Expand Down
13 changes: 13 additions & 0 deletions examples/mcp_server_handle_message.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#[cfg(feature = "latest")]
use rust_mcp_schema::schema_utils::*;
#[cfg(feature = "latest")]
use rust_mcp_schema::*;

#[cfg(feature = "2024_11_05")]
use rust_mcp_schema::mcp_2024_11_05::schema_utils::*;
#[cfg(feature = "2024_11_05")]
use rust_mcp_schema::mcp_2024_11_05::*;

#[cfg(feature = "draft")]
use rust_mcp_schema::mcp_draft::schema_utils::*;
#[cfg(feature = "draft")]
use rust_mcp_schema::mcp_draft::*;

use std::str::FromStr;

type AppError = RpcError;
Expand Down
16 changes: 9 additions & 7 deletions scripts/run_test.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/bin/bash

# common features (always included in the tests)
COMMON_FEATURES=("schema_utils")
COMMON_FEATURES=("schema_utils")

# schema versions features (tested one at a time)
SCHEMA_VERSION_FEATURES=("2025_03_26", "2024_11_05", "draft")

# space-separated string
# space-separated string
COMMON_FEATURES_STR="${COMMON_FEATURES[*]}"

for FEATURE in "${SCHEMA_VERSION_FEATURES[@]}"; do
Expand All @@ -18,10 +18,6 @@ for FEATURE in "${SCHEMA_VERSION_FEATURES[@]}"; do
echo "❌ Tests failed for: --features \"$COMMON_FEATURES_STR $FEATURE\""
exit 1
fi

echo
echo "🚀 Running documentation tests with: --features \"$COMMON_FEATURES_STR $FEATURE\""
cargo test --doc --no-default-features --features "$COMMON_FEATURES_STR $FEATURE"

# stop on failure
if [ $? -ne 0 ]; then
Expand All @@ -30,4 +26,10 @@ for FEATURE in "${SCHEMA_VERSION_FEATURES[@]}"; do
fi
done

echo "✅ All tests passed!"
# Get the first feature from the array
FEATURE="${SCHEMA_VERSION_FEATURES[0]}"
echo
echo "🚀 Running documentation tests with: --features \"$COMMON_FEATURES_STR $FEATURE\""
cargo test --doc --no-default-features --features "$COMMON_FEATURES_STR $FEATURE"

echo "✅ All tests passed!"
79 changes: 53 additions & 26 deletions src/generated_schema.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,65 @@
/// Schema Version: 2024_11_05
#[cfg(feature = "2024_11_05")]
#[path = "generated_schema/2024_11_05/mcp_schema.rs"]
mod mcp_schema;
macro_rules! define_schema_version {
(
$feature:literal,
$mod_name:ident,
$schema_path:literal,
$utils_path:literal,
$schema_mod:ident,
$utils_mod:ident
) => {
#[cfg(feature = $feature)]
#[path = $schema_path]
mod $schema_mod;

#[cfg(feature = "2024_11_05")]
pub use mcp_schema::*;
#[cfg(all(feature = "schema_utils", feature = $feature))]
#[path = $utils_path]
mod $utils_mod;

#[cfg(all(feature = "schema_utils", feature = "2024_11_05"))]
#[path = "generated_schema/2024_11_05/schema_utils.rs"]
pub mod schema_utils;
#[cfg(feature = $feature)]
pub mod $mod_name {
pub use super::$schema_mod::*;

/// Schema Version: 2025_03_26
#[cfg(feature = "2025_03_26")]
#[path = "generated_schema/2025_03_26/mcp_schema.rs"]
mod mcp_schema;
#[cfg(feature = "schema_utils")]
pub mod schema_utils {
pub use super::super::$utils_mod::*;
}
}
};
}

/// Latest MCP Protocol 2025_03_26
#[cfg(feature = "2025_03_26")]
pub use mcp_schema::*;
pub use mcp_2025_03_26::*;

#[cfg(all(feature = "schema_utils", feature = "2025_03_26"))]
#[path = "generated_schema/2025_03_26/schema_utils.rs"]
pub mod schema_utils;
#[cfg(feature = "2025_03_26")]
define_schema_version!(
"2025_03_26",
mcp_2025_03_26,
"generated_schema/2025_03_26/mcp_schema.rs",
"generated_schema/2025_03_26/schema_utils.rs",
__int_2025_03_26,
__int_utils_2025_03_26
);

/// Schema Version: draft
#[cfg(feature = "draft")]
#[path = "generated_schema/draft/mcp_schema.rs"]
mod mcp_schema;
#[cfg(feature = "2024_11_05")]
define_schema_version!(
"2024_11_05",
mcp_2024_11_05,
"generated_schema/2024_11_05/mcp_schema.rs",
"generated_schema/2024_11_05/schema_utils.rs",
__int_2024_11_05,
__int_utils_2024_11_05
);

#[cfg(feature = "draft")]
pub use mcp_schema::*;

#[cfg(all(feature = "schema_utils", feature = "draft"))]
#[path = "generated_schema/draft/schema_utils.rs"]
pub mod schema_utils;
define_schema_version!(
"draft",
mcp_draft,
"generated_schema/draft/mcp_schema.rs",
"generated_schema/draft/schema_utils.rs",
__int_draft,
__int_utils_draft
);

#[path = "generated_schema/protocol_version.rs"]
mod protocol_version;
Expand Down
2 changes: 1 addition & 1 deletion src/generated_schema/2024_11_05/schema_utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::generated_schema::*;
use crate::generated_schema::mcp_2024_11_05::*;
use serde::ser::SerializeStruct;
use serde_json::{json, Value};
use std::hash::{Hash, Hasher};
Expand Down
2 changes: 1 addition & 1 deletion src/generated_schema/draft/schema_utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::generated_schema::*;
use crate::generated_schema::mcp_draft::*;
use serde::ser::SerializeStruct;
use serde_json::{json, Value};
use std::hash::{Hash, Hasher};
Expand Down
3 changes: 0 additions & 3 deletions src/rust-mcp-schema.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
/// modules
mod generated_schema;

/// re-exports
#[cfg(feature = "schema_utils")]
pub use generated_schema::schema_utils;
pub use generated_schema::*;
8 changes: 4 additions & 4 deletions tests/2024_11_05_exclusive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pub mod common;

#[cfg(feature = "2024_11_05")]
mod test_2024_11_05_exclusive {
use rust_mcp_schema::schema_utils::*;
use rust_mcp_schema::*;
use rust_mcp_schema::mcp_2024_11_05::schema_utils::*;
use rust_mcp_schema::mcp_2024_11_05::*;

use super::common::{get_message, re_serialize};

Expand Down Expand Up @@ -73,7 +73,7 @@ mod test_2024_11_05_exclusive {

#[test]
fn test_server_list_resource_templates_result_sample() {
let message = get_message("res_template_list");
let message = get_message("res_template_list", LATEST_PROTOCOL_VERSION);
assert!(matches!(message, ServerMessage::Response(server_message)
if matches!(&server_message.result, ResultFromServer::ServerResult(server_result)
if matches!(server_result, ServerResult::ListResourceTemplatesResult(_)))
Expand All @@ -82,7 +82,7 @@ mod test_2024_11_05_exclusive {

#[test]
fn test_client_list_resource_templates_request_sample() {
let message = get_message("req_template_list");
let message = get_message("req_template_list", LATEST_PROTOCOL_VERSION);
assert!(matches!(message, ClientMessage::Request(client_message)
if matches!(&client_message.request, RequestFromClient::ClientRequest(client_request)
if matches!(client_request, ClientRequest::ListResourceTemplatesRequest(_)))
Expand Down
5 changes: 2 additions & 3 deletions tests/common/common.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use rust_mcp_schema::LATEST_PROTOCOL_VERSION;
use serde_json::Value;
use std::str::FromStr;
use std::sync::OnceLock;
Expand Down Expand Up @@ -58,11 +57,11 @@ where
}

/// get a test message payload from the sample_mcp_messages.json by key
pub fn get_message<T>(test_payload_key: &str) -> T
pub fn get_message<T>(test_payload_key: &str, version: &str) -> T
where
T: FromStr + for<'de> serde::Deserialize<'de>,
<T as FromStr>::Err: std::fmt::Debug,
{
let message_str = get_test_payload(test_payload_key).replace("PROTOCOL_VERSION", LATEST_PROTOCOL_VERSION);
let message_str = get_test_payload(test_payload_key).replace("PROTOCOL_VERSION", version);
T::from_str(&message_str).unwrap()
}
5 changes: 5 additions & 0 deletions tests/miscellaneous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
pub mod common;

mod miscellaneous_tests {
#[cfg(feature = "2024_11_05")]
use rust_mcp_schema::mcp_2024_11_05::schema_utils::*;
#[cfg(feature = "draft")]
use rust_mcp_schema::mcp_draft::schema_utils::*;
#[cfg(feature = "latest")]
use rust_mcp_schema::schema_utils::*;

#[test]
Expand Down
Loading
Loading