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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install Rust fmt
run: rustup toolchain install nightly --component rustfmt

- name: Check formatting
run: cargo fmt --all -- --check
run: cargo +nightly fmt --all -- --check

clippy:
name: Lint with Clippy
Expand Down
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cargo-features = ["edition2024"]

[workspace]
members = ["crates/rmcp", "crates/rmcp-macros", "examples/*"]
resolver = "2"
Expand All @@ -12,7 +14,7 @@ version = "0.1.5"
authors = ["4t145 <[email protected]>"]
license = "MIT/Apache-2.0"
repository = "https://github.com/modelcontextprotocol/rust-sdk/"
description = "Rust SDK for the Model Context Protocol"
description = "Rust SDK for Model Context Protocol"
keywords = ["mcp", "sdk", "tokio", "modelcontextprotocol"]
homepage = "https://github.com/modelcontextprotocol/rust-sdk"
categories = [
Expand Down
14 changes: 8 additions & 6 deletions crates/rmcp-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
cargo-features = ["edition2024"]

[package]
name = "rmcp-macros"
license.workspace = true
version.workspace = true
edition.workspace = true
repository.workspace = true
homepage.workspace = true
readme.workspace = true
license = { workspace = true }
version = { workspace = true }
edition = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
readme = { workspace = true }
description = "Rust SDK for Model Context Protocol macros library"
documentation = "https://docs.rs/rmcp-macros"

Expand Down
14 changes: 8 additions & 6 deletions crates/rmcp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
cargo-features = ["edition2024"]

[package]
name = "rmcp"
license.workspace = true
version.workspace = true
edition.workspace = true
repository.workspace = true
homepage.workspace = true
readme.workspace = true
license = { workspace = true }
version = { workspace = true }
edition = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
readme = { workspace = true }
description = "Rust SDK for Model Context Protocol"
documentation = "https://docs.rs/rmcp"

Expand Down
8 changes: 5 additions & 3 deletions crates/rmcp/src/handler/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::error::Error as McpError;
use crate::model::*;
use crate::service::{Peer, RequestContext, RoleClient, Service, ServiceRole};
use crate::{
error::Error as McpError,
model::*,
service::{Peer, RequestContext, RoleClient, Service, ServiceRole},
};

impl<H: ClientHandler> Service<RoleClient> for H {
async fn handle_request(
Expand Down
8 changes: 5 additions & 3 deletions crates/rmcp/src/handler/server.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::error::Error as McpError;
use crate::model::*;
use crate::service::{Peer, RequestContext, RoleServer, Service, ServiceRole};
use crate::{
error::Error as McpError,
model::*,
service::{Peer, RequestContext, RoleServer, Service, ServiceRole},
};

mod resource;
pub mod tool;
Expand Down
14 changes: 6 additions & 8 deletions crates/rmcp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,26 @@ pub use error::Error;
pub mod model;
#[cfg(any(feature = "client", feature = "server"))]
pub mod service;
#[cfg(feature = "client")]
pub use handler::client::ClientHandler;
#[cfg(feature = "server")]
pub use handler::server::ServerHandler;
#[cfg(any(feature = "client", feature = "server"))]
pub use service::{Peer, Service, ServiceError, ServiceExt};
#[cfg(feature = "client")]
pub use service::{RoleClient, serve_client};
#[cfg(feature = "server")]
pub use service::{RoleServer, serve_server};

#[cfg(feature = "client")]
pub use handler::client::ClientHandler;
#[cfg(feature = "server")]
pub use handler::server::ServerHandler;

pub mod handler;
pub mod transport;

#[cfg(all(feature = "macros", feature = "server"))]
pub use rmcp_macros::tool;

// re-export
#[cfg(all(feature = "macros", feature = "server"))]
pub use paste::paste;
#[cfg(all(feature = "macros", feature = "server"))]
pub use rmcp_macros::tool;
#[cfg(all(feature = "macros", feature = "server"))]
pub use schemars;
#[cfg(feature = "macros")]
pub use serde;
Expand Down
4 changes: 2 additions & 2 deletions crates/rmcp/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub use capabilities::*;
pub use content::*;
pub use prompt::*;
pub use resource::*;

use serde::{Deserialize, Serialize};
use serde_json::Value;
pub use tool::*;
Expand Down Expand Up @@ -964,9 +963,10 @@ impl From<CancelledNotification> for ClientNotification {

#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;

use super::*;

#[test]
fn test_notification_serde() {
let raw = json!( {
Expand Down
5 changes: 3 additions & 2 deletions crates/rmcp/src/model/annotated.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::ops::{Deref, DerefMut};

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

use super::{
RawContent, RawEmbeddedResource, RawImageContent, RawResource, RawResourceTemplate,
RawTextContent, Role,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
Expand Down
7 changes: 4 additions & 3 deletions crates/rmcp/src/model/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::JsonObject;
use std::{collections::BTreeMap, marker::PhantomData};

use paste::paste;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::marker::PhantomData;

use super::JsonObject;
pub type ExperimentalCapabilities = BTreeMap<String, JsonObject>;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
Expand Down
4 changes: 2 additions & 2 deletions crates/rmcp/src/model/content.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Content sent around agents, extensions, and LLMs
//! The various content types can be display to humans but also understood by models
//! They include optional annotations used to help inform agent usage
use super::resource::ResourceContents;
use super::{AnnotateAble, Annotated};
use serde::{Deserialize, Serialize};
use serde_json::json;

use super::{AnnotateAble, Annotated, resource::ResourceContents};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RawTextContent {
Expand Down
9 changes: 6 additions & 3 deletions crates/rmcp/src/model/prompt.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use super::content::{EmbeddedResource, ImageContent};
use super::resource::ResourceContents;
use super::{AnnotateAble, Annotations, RawEmbeddedResource, RawImageContent};
use base64::engine::{Engine, general_purpose::STANDARD as BASE64_STANDARD};
use serde::{Deserialize, Serialize};

use super::{
AnnotateAble, Annotations, RawEmbeddedResource, RawImageContent,
content::{EmbeddedResource, ImageContent},
resource::ResourceContents,
};

/// A prompt that can be used to generate text from a model
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down
27 changes: 15 additions & 12 deletions crates/rmcp/src/service.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::error::Error as McpError;
use crate::model::{
CancelledNotification, CancelledNotificationParam, JsonRpcMessage, Message, RequestId,
};
use crate::transport::IntoTransport;
use futures::future::BoxFuture;
use thiserror::Error;

use crate::{
error::Error as McpError,
model::{
CancelledNotification, CancelledNotificationParam, JsonRpcMessage, Message, RequestId,
},
transport::IntoTransport,
};
#[cfg(feature = "client")]
mod client;
#[cfg(feature = "client")]
Expand All @@ -15,10 +18,9 @@ mod server;
pub use server::*;
#[cfg(feature = "tower")]
mod tower;
use tokio_util::sync::CancellationToken;
#[cfg(feature = "tower")]
pub use tower::*;

use tokio_util::sync::CancellationToken;
use tracing::instrument;
#[derive(Error, Debug)]
#[non_exhaustive]
Expand Down Expand Up @@ -189,11 +191,12 @@ impl<R: ServiceRole, S: Service<R>> DynService<R> for S {
}
}

use std::collections::HashMap;
use std::ops::Deref;
use std::sync::Arc;
use std::sync::atomic::AtomicU32;
use std::time::Duration;
use std::{
collections::HashMap,
ops::Deref,
sync::{Arc, atomic::AtomicU32},
time::Duration,
};

use tokio::sync::mpsc;

Expand Down
6 changes: 3 additions & 3 deletions crates/rmcp/src/service/client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use futures::{SinkExt, StreamExt};

use super::*;
use crate::model::{
CallToolRequest, CallToolRequestParam, CallToolResult, CancelledNotification,
CancelledNotificationParam, ClientInfo, ClientMessage, ClientNotification, ClientRequest,
Expand All @@ -12,9 +15,6 @@ use crate::model::{
UnsubscribeRequest, UnsubscribeRequestParam,
};

use super::*;
use futures::{SinkExt, StreamExt};

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct RoleClient;

Expand Down
6 changes: 3 additions & 3 deletions crates/rmcp/src/service/server.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use futures::{SinkExt, StreamExt};

use super::*;
use crate::model::{
CancelledNotification, CancelledNotificationParam, ClientInfo, ClientNotification,
ClientRequest, ClientResult, CreateMessageRequest, CreateMessageRequestParam,
Expand All @@ -8,9 +11,6 @@ use crate::model::{
ServerResult, ToolListChangedNotification,
};

use super::*;
use futures::{SinkExt, StreamExt};

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct RoleServer;

Expand Down
3 changes: 1 addition & 2 deletions crates/rmcp/src/transport/child_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use tokio::{
process::{ChildStdin, ChildStdout},
};

use crate::service::{RxJsonRpcMessage, ServiceRole, TxJsonRpcMessage};

use super::IntoTransport;
use crate::service::{RxJsonRpcMessage, ServiceRole, TxJsonRpcMessage};

pub(crate) fn child_process(
mut child: tokio::process::Child,
Expand Down
4 changes: 1 addition & 3 deletions crates/rmcp/src/transport/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ use std::marker::PhantomData;
use futures::{Sink, SinkExt, Stream, StreamExt};
use serde::{Serialize, de::DeserializeOwned};
use thiserror::Error;

use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::{
bytes::{Buf, BufMut, BytesMut},
codec::{Decoder, Encoder, FramedRead, FramedWrite},
};

use crate::service::{RxJsonRpcMessage, ServiceRole, TxJsonRpcMessage};

use super::IntoTransport;
use crate::service::{RxJsonRpcMessage, ServiceRole, TxJsonRpcMessage};

#[cfg(feature = "transport-io")]
/// # StdIO Transport
Expand Down
6 changes: 4 additions & 2 deletions crates/rmcp/src/transport/sse.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
//! reference: https://html.spec.whatwg.org/multipage/server-sent-events.html
use crate::model::{ClientJsonRpcMessage, ServerJsonRpcMessage};
use std::{collections::VecDeque, sync::Arc, time::Duration};

use futures::{FutureExt, Sink, Stream, StreamExt, future::BoxFuture, stream::BoxStream};
use reqwest::{
Client as HttpClient, IntoUrl, Url,
header::{ACCEPT, HeaderValue},
};
use sse_stream::{Error as SseError, Sse, SseStream};
use std::{collections::VecDeque, sync::Arc, time::Duration};
use thiserror::Error;

use crate::model::{ClientJsonRpcMessage, ServerJsonRpcMessage};
const MIME_TYPE: &str = "text/event-stream";
const HEADER_LAST_EVENT_ID: &str = "Last-Event-ID";

Expand Down
16 changes: 8 additions & 8 deletions crates/rmcp/src/transport/sse_server.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::{
RoleServer, Service,
model::ClientJsonRpcMessage,
service::{RxJsonRpcMessage, TxJsonRpcMessage},
};
use std::{collections::HashMap, net::SocketAddr, sync::Arc};

use axum::{
Json, Router,
extract::{Query, State},
Expand All @@ -14,13 +11,16 @@ use axum::{
routing::{get, post},
};
use futures::{Sink, SinkExt, Stream, StreamExt};
use std::{collections::HashMap, net::SocketAddr};
use tokio::io;
use tokio_stream::wrappers::ReceiverStream;
use tokio_util::sync::{CancellationToken, PollSender};
use tracing::Instrument;

use std::sync::Arc;
use tokio::io;
use crate::{
RoleServer, Service,
model::ClientJsonRpcMessage,
service::{RxJsonRpcMessage, TxJsonRpcMessage},
};
type SessionId = Arc<str>;
type TxStore =
Arc<tokio::sync::RwLock<HashMap<SessionId, tokio::sync::mpsc::Sender<ClientJsonRpcMessage>>>>;
Expand Down
1 change: 0 additions & 1 deletion crates/rmcp/tests/test_tool_macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use rmcp::{ServerHandler, handler::server::tool::ToolCallContext, tool};
use schemars::JsonSchema;

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, JsonSchema)]
Expand Down
2 changes: 2 additions & 0 deletions examples/clients/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cargo-features = ["edition2024"]

[package]
name = "mcp-client-examples"
version = "0.1.5"
Expand Down
7 changes: 2 additions & 5 deletions examples/clients/src/collection.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use std::collections::HashMap;

use anyhow::Result;
use rmcp::service::ServiceExt;
use rmcp::{model::CallToolRequestParam, transport::TokioChildProcess};

use rmcp::{model::CallToolRequestParam, service::ServiceExt, transport::TokioChildProcess};
use tokio::process::Command;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

#[tokio::main]
async fn main() -> Result<()> {
Expand Down
Loading
Loading