agenterra_rmcp/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3//! The official Rust SDK for the Model Context Protocol (MCP).
4//!
5//! The MCP is a protocol that allows AI assistants to communicate with other
6//! services. `rmcp` is the official Rust implementation of this protocol.
7//!
8//! There are two ways in which the library can be used, namely to build a
9//! server or to build a client.
10//!
11//! ## Server
12//!
13//! A server is a service that exposes capabilities. For example, a common
14//! use-case is for the server to make multiple tools available to clients such
15//! as Claude Desktop or the Cursor IDE.
16//!
17//! For example, to implement a server that has a tool that can count, you would
18//! make an object for that tool and add an implementation with the `#[tool_router]` macro:
19//!
20//! ```rust
21//! use std::sync::Arc;
22//! use agenterra_rmcp::{Error as McpError, model::*, tool, tool_router, handler::server::tool::ToolRouter};
23//! use tokio::sync::Mutex;
24//!
25//! #[derive(Clone)]
26//! pub struct Counter {
27//!     counter: Arc<Mutex<i32>>,
28//!     tool_router: ToolRouter<Self>,
29//! }
30//!
31//! #[tool_router]
32//! impl Counter {
33//!     fn new() -> Self {
34//!         Self {
35//!             counter: Arc::new(Mutex::new(0)),
36//!             tool_router: Self::tool_router(),
37//!         }
38//!     }
39//!
40//!     #[tool(description = "Increment the counter by 1")]
41//!     async fn increment(&self) -> Result<CallToolResult, McpError> {
42//!         let mut counter = self.counter.lock().await;
43//!         *counter += 1;
44//!         Ok(CallToolResult::success(vec![Content::text(
45//!             counter.to_string(),
46//!         )]))
47//!     }
48//! }
49//! ```
50//!
51//! Next also implement [ServerHandler] for `Counter` and start the server inside
52//! `main` by calling `Counter::new().serve(...)`. See the examples directory in the repository for more information.
53//!
54//! ## Client
55//!
56//! A client can be used to interact with a server. Clients can be used to get a
57//! list of the available tools and to call them. For example, we can `uv` to
58//! start a MCP server in Python and then list the tools and call `git status`
59//! as follows:
60//!
61//! ```rust
62//! use anyhow::Result;
63//! use agenterra_rmcp::{model::CallToolRequestParam, service::ServiceExt, transport::{TokioChildProcess, ConfigureCommandExt}};
64//! use tokio::process::Command;
65//!
66//! async fn client() -> Result<()> {
67//!     let service = ().serve(TokioChildProcess::new(Command::new("uvx").configure(|cmd| {
68//!         cmd.arg("mcp-server-git");
69//!     }))?).await?;
70//!
71//!     // Initialize
72//!     let server_info = service.peer_info();
73//!     println!("Connected to server: {server_info:#?}");
74//!
75//!     // List tools
76//!     let tools = service.list_tools(Default::default()).await?;
77//!     println!("Available tools: {tools:#?}");
78//!
79//!     // Call tool 'git_status' with arguments = {"repo_path": "."}
80//!     let tool_result = service
81//!         .call_tool(CallToolRequestParam {
82//!             name: "git_status".into(),
83//!             arguments: serde_json::json!({ "repo_path": "." }).as_object().cloned(),
84//!         })
85//!         .await?;
86//!     println!("Tool result: {tool_result:#?}");
87//!
88//!     service.cancel().await?;
89//!     Ok(())
90//! }
91//! ```
92mod error;
93pub use error::Error;
94
95/// Basic data types in MCP specification
96pub mod model;
97#[cfg(any(feature = "client", feature = "server"))]
98#[cfg_attr(docsrs, doc(cfg(any(feature = "client", feature = "server"))))]
99pub mod service;
100#[cfg(feature = "client")]
101#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
102pub use handler::client::ClientHandler;
103#[cfg(feature = "server")]
104#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
105pub use handler::server::ServerHandler;
106#[cfg(any(feature = "client", feature = "server"))]
107#[cfg_attr(docsrs, doc(cfg(any(feature = "client", feature = "server"))))]
108pub use service::{Peer, Service, ServiceError, ServiceExt};
109#[cfg(feature = "client")]
110#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
111pub use service::{RoleClient, serve_client};
112#[cfg(feature = "server")]
113#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
114pub use service::{RoleServer, serve_server};
115
116pub mod handler;
117pub mod transport;
118
119// re-export
120#[cfg(all(feature = "macros", feature = "server"))]
121#[cfg_attr(docsrs, doc(cfg(all(feature = "macros", feature = "server"))))]
122pub use agenterra_rmcp_macros::*;
123#[cfg(all(feature = "macros", feature = "server"))]
124#[cfg_attr(docsrs, doc(cfg(all(feature = "macros", feature = "server"))))]
125pub use paste::paste;
126#[cfg(all(feature = "macros", feature = "server"))]
127#[cfg_attr(docsrs, doc(cfg(all(feature = "macros", feature = "server"))))]
128pub use schemars;
129#[cfg(feature = "macros")]
130#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
131pub use serde;
132#[cfg(feature = "macros")]
133#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
134pub use serde_json;