ci: add documentation generation job (#59)
* ci: add documentation generation job 1. add doc ci in workflow 2. remove the readme in rmcp crate Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn> * docs: fix doc test in README.md 1) fix doc test in readme 2) fix some fmt Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn> --------- Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn>
This commit is contained in:
parent
0eea9aad4a
commit
b91fe54409
4 changed files with 24 additions and 187 deletions
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
|
|
@ -90,6 +90,23 @@ jobs:
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --all-features
|
run: cargo test --all-features
|
||||||
|
|
||||||
|
doc:
|
||||||
|
name: Generate Documentation
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Generate documentation
|
||||||
|
run: |
|
||||||
|
cargo doc --no-deps -p rmcp -p rmcp-macros
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: -Dwarnings
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release crates
|
name: Release crates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -24,9 +24,13 @@ Start a client in one line:
|
||||||
use rmcp::{ServiceExt, transport::TokioChildProcess};
|
use rmcp::{ServiceExt, transport::TokioChildProcess};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
let client = ().serve(
|
#[tokio::main]
|
||||||
TokioChildProcess::new(Command::new("npx").arg("-y").arg("@modelcontextprotocol/server-everything"))?
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
).await?;
|
let client = ().serve(
|
||||||
|
TokioChildProcess::new(Command::new("npx").arg("-y").arg("@modelcontextprotocol/server-everything"))?
|
||||||
|
).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 1. Build a transport
|
#### 1. Build a transport
|
||||||
|
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
# RMCP
|
|
||||||
[](https://crates.io/crates/rmcp)
|
|
||||||

|
|
||||||
[](https://docs.rs/rmcp/latest/rmcp)
|
|
||||||
|
|
||||||
A better and clean rust Model Context Protocol SDK implementation with tokio async runtime.
|
|
||||||
|
|
||||||
## Comparing to official SDK
|
|
||||||
|
|
||||||
The [Official SDK](https://github.com/modelcontextprotocol/rust-sdk/pulls) has too much limit and it was originally built for [goose](https://github.com/block/goose) rather than general using purpose.
|
|
||||||
|
|
||||||
All the features listed on specification would be implemented in this crate. And the first and most important thing is, this crate has the correct and intact data [types](crate::model). See it yourself.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Import
|
|
||||||
```toml
|
|
||||||
rmcp = { version = "0.1", features = ["server"] }
|
|
||||||
```
|
|
||||||
|
|
||||||
### Quick start
|
|
||||||
Start a client in one line:
|
|
||||||
```rust,ignore
|
|
||||||
# use rmcp::{ServiceExt, transport::child_process::TokioChildProcess};
|
|
||||||
# use tokio::process::Command;
|
|
||||||
|
|
||||||
let client = ().serve(
|
|
||||||
TokioChildProcess::new(Command::new("npx").arg("-y").arg("@modelcontextprotocol/server-everything"))?
|
|
||||||
).await?;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Start a client in one line:
|
|
||||||
```rust,ignore
|
|
||||||
# use rmcp::{ServiceExt, transport::TokioChildProcess};
|
|
||||||
# use tokio::process::Command;
|
|
||||||
|
|
||||||
let client = ().serve(
|
|
||||||
TokioChildProcess::new(Command::new("npx").arg("-y").arg("@modelcontextprotocol/server-everything"))?
|
|
||||||
).await?;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### 1. Build a transport
|
|
||||||
The transport type must implemented [`IntoTransport`](crate::transport::IntoTransport) trait, which allow split into a sink and a stream.
|
|
||||||
|
|
||||||
For client, the sink item is [`ClientJsonRpcMessage`](crate::model::ClientJsonRpcMessage) and stream item is [`ServerJsonRpcMessage`](crate::model::ServerJsonRpcMessage)
|
|
||||||
|
|
||||||
For server, the sink item is [`ServerJsonRpcMessage`](crate::model::ServerJsonRpcMessage) and stream item is [`ClientJsonRpcMessage`](crate::model::ClientJsonRpcMessage)
|
|
||||||
|
|
||||||
##### These types is automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait
|
|
||||||
1. For type that already implement both [`Sink`](futures::Sink) and [`Stream`](futures::Stream) trait, they are automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait
|
|
||||||
2. For tuple of sink `Tx` and stream `Rx`, type `(Tx, Rx)` are automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait
|
|
||||||
3. For type that implement both [`tokio::io::AsyncRead`] and [`tokio::io::AsyncWrite`] trait, they are automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait
|
|
||||||
4. For tuple of [`tokio::io::AsyncRead`] `R `and [`tokio::io::AsyncWrite`] `W`, type `(R, W)` are automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait
|
|
||||||
|
|
||||||
|
|
||||||
```rust, ignore
|
|
||||||
use tokio::io::{stdin, stdout};
|
|
||||||
let transport = (stdin(), stdout());
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. Build a service
|
|
||||||
You can easily build a service by using [`ServerHandler`](crate::handler::server) or [`ClientHandler`](crate::handler::client).
|
|
||||||
|
|
||||||
```rust, ignore
|
|
||||||
let service = common::counter::Counter::new();
|
|
||||||
```
|
|
||||||
|
|
||||||
Or if you want to use `tower`, you can [`TowerHandler`] as a adapter.
|
|
||||||
|
|
||||||
You can reference the [server examples](https://github.commodelcontextprotocol/rust-sdk/tree/release/examples/servers).
|
|
||||||
|
|
||||||
#### 3. Serve them together
|
|
||||||
```rust, ignore
|
|
||||||
// this call will finish the initialization process
|
|
||||||
let server = service.serve(transport).await?;
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Interact with the server
|
|
||||||
Once the server is initialized, you can send requests or notifications:
|
|
||||||
|
|
||||||
```rust, ignore
|
|
||||||
// request
|
|
||||||
let roots = server.list_roots().await?;
|
|
||||||
|
|
||||||
// or send notification
|
|
||||||
server.notify_cancelled(...).await?;
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5. Waiting for service shutdown
|
|
||||||
```rust, ignore
|
|
||||||
let quit_reason = server.waiting().await?;
|
|
||||||
// or cancel it
|
|
||||||
let quit_reason = server.cancel().await?;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use marcos to declaring tool
|
|
||||||
Use `toolbox` and `tool` macros to create tool quickly.
|
|
||||||
|
|
||||||
Check this [file](https://github.commodelcontextprotocol/rust-sdk/tree/release/examples/servers/src/common/calculator.rs).
|
|
||||||
```rust, ignore
|
|
||||||
use rmcp::{ServerHandler, model::ServerInfo, schemars, tool};
|
|
||||||
|
|
||||||
use super::counter::Counter;
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
|
||||||
pub struct SumRequest {
|
|
||||||
#[schemars(description = "the left hand side number")]
|
|
||||||
pub a: i32,
|
|
||||||
#[schemars(description = "the right hand side number")]
|
|
||||||
pub b: i32,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Calculator;
|
|
||||||
|
|
||||||
// create a static toolbox to store the tool attributes
|
|
||||||
#[tool(tool_box)]
|
|
||||||
impl Calculator {
|
|
||||||
// async function
|
|
||||||
#[tool(description = "Calculate the sum of two numbers")]
|
|
||||||
async fn sum(&self, #[tool(aggr)] SumRequest { a, b }: SumRequest) -> String {
|
|
||||||
(a + b).to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync function
|
|
||||||
#[tool(description = "Calculate the sum of two numbers")]
|
|
||||||
fn sub(
|
|
||||||
&self,
|
|
||||||
#[tool(param)]
|
|
||||||
// this macro will transfer the schemars and serde's attributes
|
|
||||||
#[schemars(description = "the left hand side number")]
|
|
||||||
a: i32,
|
|
||||||
#[tool(param)]
|
|
||||||
#[schemars(description = "the right hand side number")]
|
|
||||||
b: i32,
|
|
||||||
) -> String {
|
|
||||||
(a - b).to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl call_tool and list_tool by querying static toolbox
|
|
||||||
#[tool(tool_box)]
|
|
||||||
impl ServerHandler for Calculator {
|
|
||||||
fn get_info(&self) -> ServerInfo {
|
|
||||||
ServerInfo {
|
|
||||||
instructions: Some("A simple calculator".into()),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
The only thing you should do is to make the function's return type implement `IntoCallToolResult`.
|
|
||||||
|
|
||||||
And you can just implement `IntoContents`, and the return value will be marked as success automatically.
|
|
||||||
|
|
||||||
If you return a type of `Result<T, E>` where `T` and `E` both implemented `IntoContents`, it's also OK.
|
|
||||||
|
|
||||||
### Manage Multi Services
|
|
||||||
For many cases you need to manage several service in a collection, you can call `into_dyn` to convert services into the same type.
|
|
||||||
```rust, ignore
|
|
||||||
let service = service.into_dyn();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
See [examples](https://github.commodelcontextprotocol/rust-sdk/tree/release/examples/README.md)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
- `client`: use client side sdk
|
|
||||||
- `server`: use server side sdk
|
|
||||||
- `macros`: macros default
|
|
||||||
#### Transports
|
|
||||||
- `transport-io`: Server stdio transport
|
|
||||||
- `transport-sse-server`: Server SSE transport
|
|
||||||
- `transport-child-process`: Client stdio transport
|
|
||||||
- `transport-sse`: Client sse transport
|
|
||||||
|
|
||||||
## Related Resources
|
|
||||||
- [MCP Specification](https://spec.modelcontextprotocol.io/specification/2024-11-05/)
|
|
||||||
|
|
||||||
- [Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.ts)
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
|
|
||||||
mod error;
|
mod error;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue