Skip to content

Commit c1c4c9a

Browse files
authored
doc: use hierarchical readme for publishing (#198)
1 parent a3b42c4 commit c1c4c9a

File tree

3 files changed

+292
-122
lines changed

3 files changed

+292
-122
lines changed

README.md

Lines changed: 32 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
<div align = "right">
2-
<a href="docs/readme/README.zh-cn.md">简体中文</a>
2+
<a href="docs/readme/README.zh-cn.md">简体中文(待更新)</a>
33
</div>
44

55
# RMCP
6-
7-
[![Crates.io Version](https://img.shields.io/crates/v/rmcp)](https://crates.io/crates/rmcp)
8-
![Release status](https://github.com/modelcontextprotocol/rust-sdk/actions/workflows/release.yml/badge.svg)
9-
[![docs.rs](https://img.shields.io/docsrs/rmcp)](https://docs.rs/rmcp/latest/rmcp)
6+
Wait for the first release.
7+
<!-- [![Crates.io Version](todo)](todo) -->
8+
<!-- ![Release status](https://github.com/modelcontextprotocol/rust-sdk/actions/workflows/release.yml/badge.svg) -->
9+
<!-- [![docs.rs](todo)](todo) -->
1010
![Coverage](coverage.svg)
1111

1212
An official rust Model Context Protocol SDK implementation with tokio async runtime.
1313

14+
15+
This repository contains the following crates:
16+
17+
- [rmcp](crates/rmcp): The core crate providing the RMCP protocol implementation( If you want to get more information, please visit [rmcp](crates/rmcp/README.md))
18+
- [rmcp-macros](crates/rmcp-macros): A procedural macro crate for generating RMCP tool implementations(If you want to get more information, please visit [rmcp-macros](crates/rmcp-macros/README.md))
19+
1420
## Usage
1521

16-
### Import
22+
### Import the crate
1723

1824
```toml
1925
rmcp = { version = "0.1", features = ["server"] }
2026
## or dev channel
2127
rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "main" }
2228
```
29+
### Third Dependencies
30+
Basic dependencies:
31+
- [tokio required](https://github.com/tokio-rs/tokio)
32+
- [serde required](https://github.com/serde-rs/serde)
2333

24-
### Quick start
2534

26-
Start a client:
35+
36+
### Build a Client
37+
<details>
38+
<summary>Start a client</summary>
2739

2840
```rust, ignore
2941
use rmcp::{ServiceExt, transport::{TokioChildProcess, ConfigureCommandExt}};
@@ -37,39 +49,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
3749
Ok(())
3850
}
3951
```
52+
</details>
53+
54+
### Build a Server
4055

4156
<details>
42-
<summary>1. Build a transport</summary>
57+
<summary>Build a transport</summary>
4358

4459
```rust, ignore
4560
use tokio::io::{stdin, stdout};
4661
let transport = (stdin(), stdout());
4762
```
4863

49-
#### Transport
50-
The transport type must implemented [`Transport`] trait, which allow it send message concurrently and receive message sequentially.
51-
There are 3 pairs of standard transport types:
52-
53-
| transport | client | server |
54-
|:-: |:-: |:-: |
55-
| std IO | [`child_process::TokioChildProcess`] | [`io::stdio`] |
56-
| streamable http | [`streamable_http_client::StreamableHttpClientTransport`] | [`streamable_http_server::session::create_session`] |
57-
| sse | [`sse_client::SseClientTransport`] | [`sse_server::SseServer`] |
58-
59-
#### [IntoTransport](`IntoTransport`) trait
60-
[`IntoTransport`] is a helper trait that implicitly convert a type into a transport type.
61-
62-
These types is automatically implemented [`IntoTransport`] trait
63-
1. A type that already implement both [`futures::Sink`] and [`futures::Stream`] trait, or a tuple `(Tx, Rx)` where `Tx` is [`futures::Sink`] and `Rx` is [`futures::Stream`].
64-
2. A type that implement both [`tokio::io::AsyncRead`] and [`tokio::io::AsyncWrite`] trait. or a tuple `(R, W)` where `R` is [`tokio::io::AsyncRead`] and `W` is [`tokio::io::AsyncWrite`].
65-
3. A type that implement [Worker](`worker::Worker`) trait.
66-
4. A type that implement [`Transport`] trait.
67-
68-
For example, you can see how we build a transport through TCP stream or http upgrade so easily. [examples](examples/README.md)
6964
</details>
7065

7166
<details>
72-
<summary>2. Build a service</summary>
67+
<summary>Build a service</summary>
7368

7469
You can easily build a service by using [`ServerHandler`](crates/rmcp/src/handler/server.rs) or [`ClientHandler`](crates/rmcp/src/handler/client.rs).
7570

@@ -79,7 +74,7 @@ let service = common::counter::Counter::new();
7974
</details>
8075

8176
<details>
82-
<summary>3. Serve them together</summary>
77+
<summary>Start the server</summary>
8378

8479
```rust, ignore
8580
// this call will finish the initialization process
@@ -88,7 +83,7 @@ let server = service.serve(transport).await?;
8883
</details>
8984

9085
<details>
91-
<summary>4. Interact with the server</summary>
86+
<summary>Interact with the server</summary>
9287

9388
Once the server is initialized, you can send requests or notifications:
9489

@@ -102,7 +97,7 @@ server.notify_cancelled(...).await?;
10297
</details>
10398

10499
<details>
105-
<summary>5. Waiting for service shutdown</summary>
100+
<summary>Waiting for service shutdown</summary>
106101

107102
```rust, ignore
108103
let quit_reason = server.waiting().await?;
@@ -111,104 +106,19 @@ let quit_reason = server.cancel().await?;
111106
```
112107
</details>
113108

114-
### Use macros to declaring tool
115-
116-
Use `toolbox` and `tool` macros to create tool quickly.
117-
118-
<details>
119-
<summary>Example: Calculator Tool</summary>
120-
121-
Check this [file](examples/servers/src/common/calculator.rs).
122-
```rust, ignore
123-
use rmcp::{ServerHandler, model::ServerInfo, schemars, tool};
124-
125-
use super::counter::Counter;
126-
127-
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
128-
pub struct SumRequest {
129-
#[schemars(description = "the left hand side number")]
130-
pub a: i32,
131-
#[schemars(description = "the right hand side number")]
132-
pub b: i32,
133-
}
134-
#[derive(Debug, Clone)]
135-
pub struct Calculator;
136-
137-
// create a static toolbox to store the tool attributes
138-
#[tool(tool_box)]
139-
impl Calculator {
140-
// async function
141-
#[tool(description = "Calculate the sum of two numbers")]
142-
async fn sum(&self, #[tool(aggr)] SumRequest { a, b }: SumRequest) -> String {
143-
(a + b).to_string()
144-
}
145-
146-
// sync function
147-
#[tool(description = "Calculate the difference of two numbers")]
148-
fn sub(
149-
&self,
150-
#[tool(param)]
151-
// this macro will transfer the schemars and serde's attributes
152-
#[schemars(description = "the left hand side number")]
153-
a: i32,
154-
#[tool(param)]
155-
#[schemars(description = "the right hand side number")]
156-
b: i32,
157-
) -> String {
158-
(a - b).to_string()
159-
}
160-
}
161-
162-
// impl call_tool and list_tool by querying static toolbox
163-
#[tool(tool_box)]
164-
impl ServerHandler for Calculator {
165-
fn get_info(&self) -> ServerInfo {
166-
ServerInfo {
167-
instructions: Some("A simple calculator".into()),
168-
..Default::default()
169-
}
170-
}
171-
}
172-
```
173-
174-
175-
The only thing you should do is to make the function's return type implement `IntoCallToolResult`.
176-
177-
And you can just implement `IntoContents`, and the return value will be marked as success automatically.
178-
179-
If you return a type of `Result<T, E>` where `T` and `E` both implemented `IntoContents`, it's also OK.
180-
</details>
181-
182-
### Manage Multi Services
183109

184-
For many cases you need to manage several service in a collection, you can call `into_dyn` to convert services into the same type.
185-
```rust, ignore
186-
let service = service.into_dyn();
187-
```
188110

189-
### OAuth Support
190111

191-
See [docs/OAUTH_SUPPORT.md](docs/OAUTH_SUPPORT.md) for details.
192-
193-
### Examples
112+
## Examples
194113

195114
See [examples](examples/README.md)
196115

197-
### Features
116+
## OAuth Support
117+
118+
See [oauth_support](docs/OAUTH_SUPPORT.md) for details.
198119

199-
- `client`: use client side sdk
200-
- `server`: use server side sdk
201-
- `macros`: macros default
202-
- `schemars`: implement `JsonSchema` for all model structs
203120

204-
#### Transports
205121

206-
- `transport-io`: Server stdio transport
207-
- `transport-sse-server`: Server SSE transport
208-
- `transport-child-process`: Client stdio transport
209-
- `transport-sse-client`: Client sse transport
210-
- `transport-streamable-http-server` streamable http server transport
211-
- `transport-streamable-client-server` streamable http server transport
212122

213123

214124
## Related Resources

crates/rmcp-macros/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# rmcp-macros
2+
3+
`rmcp-macros` is a procedural macro library for the Rust Model Context Protocol (RMCP) SDK, providing macros that facilitate the development of RMCP applications.
4+
5+
## Features
6+
7+
This library primarily provides the following macros:
8+
9+
- `#[tool]`: Used to mark functions as RMCP tools, automatically generating necessary metadata and invocation mechanisms
10+
11+
## Usage
12+
13+
### Tool Macro
14+
15+
Mark a function as a tool:
16+
17+
```rust ignore
18+
#[tool]
19+
fn calculator(&self, #[tool(param)] a: i32, #[tool(param)] b: i32) -> Result<CallToolResult, Error> {
20+
// Implement tool functionality
21+
Ok(CallToolResult::success(vec![Content::text((a + b).to_string())]))
22+
}
23+
24+
```
25+
26+
Use on an impl block to automatically register multiple tools:
27+
28+
```rust ignore
29+
#[tool(tool_box)]
30+
impl MyHandler {
31+
#[tool]
32+
fn tool1(&self) -> Result<CallToolResult, Error> {
33+
// Tool 1 implementation
34+
}
35+
36+
#[tool]
37+
fn tool2(&self) -> Result<CallToolResult, Error> {
38+
// Tool 2 implementation
39+
}
40+
}
41+
```
42+
43+
44+
45+
## Advanced Features
46+
47+
- Support for parameter aggregation (`#[tool(aggr)]`)
48+
- Support for custom tool names and descriptions
49+
- Automatic generation of tool descriptions from documentation comments
50+
- JSON Schema generation for tool parameters
51+
52+
## License
53+
54+
Please refer to the LICENSE file in the project root directory.

0 commit comments

Comments
 (0)