Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
/rmcpPublic

BEST Rust SDK for MCP (Model Context Protocol)

License

NotificationsYou must be signed in to change notification settings

4t145/rmcp

Repository files navigation

RMCP

Crates.io VersionRelease statusdocs.rs

A better and clean rust Model Context Protocol SDK implementation with tokio async runtime.

Comparing to official SDK

TheOfficial SDK has too much limit and it was originally built forgoose 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 datatypes. See it yourself.

Usage

Import

rmcp = {version ="0.1",features = ["server"] }## or dev channelrmcp = {git ="https://github.com/4t145/rmcp",branch ="dev" }

Quick start

Start a client in one line:

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

use tokio::io::{stdin, stdout};let transport =(stdin(),stdout());

The transport type must implementedIntoTransport trait, which allow split into a sink and a stream.

For client, the sink item isClientJsonRpcMessage and stream item isServerJsonRpcMessage

For server, the sink item isServerJsonRpcMessage and stream item isClientJsonRpcMessage

These types is automatically implementedIntoTransport trait
  1. The types that already implement bothSink andStream trait.
  2. A tuple of sinkTx and streamRx:(Tx, Rx).
  3. The type that implement both [tokio::io::AsyncRead] and [tokio::io::AsyncWrite] trait.
  4. A tuple of [tokio::io::AsyncRead]Rand [tokio::io::AsyncWrite]W:(R, W).

For example, you can see how we build a transport through TCP stream or http upgrade so easily.examples

2. Build a service

You can easily build a service by usingServerHandler orClientHandler.

let service = common::counter::Counter::new();

3. Serve them together

// this call will finish the initialization processlet server = service.serve(transport).await?;

4. Interact with the server

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

// requestlet roots = server.list_roots().await?;// or send notificationserver.notify_cancelled(...).await?;

5. Waiting for service shutdown

let quit_reason = server.waiting().await?;// or cancel itlet quit_reason = server.cancel().await?;

Use marcos to declaring tool

Usetoolbox andtool macros to create tool quickly.

Check thisfile.

use rmcp::{ServerHandler, model::ServerInfo, schemars, tool};usesuper::counter::Counter;#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]pubstructSumRequest{#[schemars(description ="the left hand side number")]puba:i32,#[schemars(description ="the right hand side number")]pubb:i32,}#[derive(Debug,Clone)]pubstructCalculator;// create a static toolbox to store the tool attributes#[tool(tool_box)]implCalculator{// async function#[tool(description ="Calculate the sum of two numbers")]asyncfnsum(&self,#[tool(aggr)]SumRequest{ a, b}:SumRequest) ->String{(a + b).to_string()}// sync function#[tool(description ="Calculate the sum of two numbers")]fnsub(&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)]implServerHandlerforCalculator{fnget_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 implementIntoCallToolResult.

And you can just implementIntoContents, and the return value will be marked as success automatically.

If you return a type ofResult<T, E> whereT andE both implementedIntoContents, it's also OK.

Manage Multi Services

For many cases you need to manage several service in a collection, you can callinto_dyn to convert services into the same type.

let service = service.into_dyn();

Examples

Seeexamples

Features

  • client: use client side sdk
  • server: use server side sdk

Related Resources


[8]ページ先頭

©2009-2025 Movatter.jp