{"id":26584162,"url":"https://github.com/4t145/rmcp","last_synced_at":"2025-03-23T09:19:27.599Z","repository":{"id":282290994,"uuid":"948093691","full_name":"4t145/rmcp","owner":"4t145","description":"Rust SDK for MCP (Model Context Protocol)","archived":false,"fork":false,"pushed_at":"2025-03-21T11:55:03.000Z","size":225,"stargazers_count":13,"open_issues_count":4,"forks_count":5,"subscribers_count":2,"default_branch":"dev","last_synced_at":"2025-03-21T12:51:34.852Z","etag":null,"topics":["llm","mcp","modelcontextprotocol","rust","sdk","sdk-rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4t145.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-13T18:31:44.000Z","updated_at":"2025-03-21T12:20:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"1ab6924e-afb1-4364-a1db-20e8776773cf","html_url":"https://github.com/4t145/rmcp","commit_stats":null,"previous_names":["4t145/rmcp"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Frmcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Frmcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Frmcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Frmcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4t145","download_url":"https://codeload.github.com/4t145/rmcp/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245079008,"owners_count":20557397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["llm","mcp","modelcontextprotocol","rust","sdk","sdk-rust"],"created_at":"2025-03-23T09:19:27.125Z","updated_at":"2025-03-23T09:19:27.588Z","avatar_url":"https://github.com/4t145.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align = \"right\"\u003e\n\u003ca href=\"docs/readme/README.zh-cn.md\"\u003e简体中文\u003c/a\u003e\n\u003c/div\u003e\n\n# RMCP\n[![Crates.io Version](https://img.shields.io/crates/v/rmcp)](https://crates.io/crates/rmcp)\n![Release status](https://github.com/4t145/rmcp/actions/workflows/release.yml/badge.svg)\n[![docs.rs](https://img.shields.io/docsrs/rmcp)](https://docs.rs/rmcp/latest/rmcp)\n\nA better and clean rust Model Context Protocol SDK implementation with tokio async runtime.\n\n## Comparing to official SDK\n\nThe [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.\n\nAll 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](crates/rmcp/src/model.rs). See it yourself. \n\n## Usage\n\n### Import\n```toml\nrmcp = { version = \"0.1\", features = [\"server\"] }\n## or dev channel\nrmcp = { git = \"https://github.com/4t145/rmcp\", branch = \"dev\" }\n```\n\n### Quick start\nStart a client in one line:\n```rust\nuse rmcp::{ServiceExt, transport::child_process::TokioChildProcess};\nuse tokio::process::Command;\n\nlet client = ().serve(\n    TokioChildProcess::new(Command::new(\"npx\").arg(\"-y\").arg(\"@modelcontextprotocol/server-everything\"))?\n).await?;\n```\n\n#### 1. Build a transport\n\n```rust, ignore\nuse tokio::io::{stdin, stdout};\nlet transport = (stdin(), stdout());\n```\n\nThe transport type must implemented [`IntoTransport`](crate::transport::IntoTransport) trait, which allow split into a sink and a stream.\n\nFor client, the sink item is [`ClientJsonRpcMessage`](crate::model::ClientJsonRpcMessage) and stream item is [`ServerJsonRpcMessage`](crate::model::ServerJsonRpcMessage)\n\nFor server, the sink item is [`ServerJsonRpcMessage`](crate::model::ServerJsonRpcMessage) and stream item is [`ClientJsonRpcMessage`](crate::model::ClientJsonRpcMessage)\n\n##### These types is automatically implemented [`IntoTransport`](crate::transport::IntoTransport) trait\n1. The types that already implement both [`Sink`](futures::Sink) and [`Stream`](futures::Stream) trait.\n2. A tuple of sink `Tx` and stream `Rx`: `(Tx, Rx)`.\n3. The type that implement both [`tokio::io::AsyncRead`] and [`tokio::io::AsyncWrite`] trait.\n4. A tuple of [`tokio::io::AsyncRead`] `R `and [`tokio::io::AsyncWrite`] `W`:  `(R, W)`.\n\nFor example, you can see how we build a transport through TCP stream or http upgrade so easily. [examples](examples/README.md)\n\n#### 2. Build a service\nYou can easily build a service by using [`ServerHandler`](crates/rmcp/src/handler/server.rs) or [`ClientHandler`](crates/rmcp/src/handler/client.rs).\n\n```rust, ignore\nlet service = common::counter::Counter::new();\n```\n\n#### 3. Serve them together\n```rust, ignore\n// this call will finish the initialization process\nlet server = service.serve(transport).await?;\n```\n\n#### 4. Interact with the server\nOnce the server is initialized, you can send requests or notifications:\n\n```rust, ignore\n// request \nlet roots = server.list_roots().await?;\n\n// or send notification\nserver.notify_cancelled(...).await?;\n```\n\n#### 5. Waiting for service shutdown\n```rust, ignore\nlet quit_reason = server.waiting().await?;\n// or cancel it\nlet quit_reason = server.cancel().await?;\n```\n\n### Use marcos to declaring tool\nUse `toolbox` and `tool` macros to create tool quickly.\n\nCheck this [file](examples/servers/src/common/calculator.rs).\n```rust, ignore\nuse rmcp::{ServerHandler, model::ServerInfo, schemars, tool};\n\nuse super::counter::Counter;\n\n#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]\npub struct SumRequest {\n    #[schemars(description = \"the left hand side number\")]\n    pub a: i32,\n    #[schemars(description = \"the right hand side number\")]\n    pub b: i32,\n}\n#[derive(Debug, Clone)]\npub struct Calculator;\n\n// create a static toolbox to store the tool attributes\n#[tool(tool_box)]\nimpl Calculator {\n    // async function\n    #[tool(description = \"Calculate the sum of two numbers\")]\n    async fn sum(\u0026self, #[tool(aggr)] SumRequest { a, b }: SumRequest) -\u003e String {\n        (a + b).to_string()\n    }\n\n    // sync function\n    #[tool(description = \"Calculate the sum of two numbers\")]\n    fn sub(\n        \u0026self,\n        #[tool(param)]\n        // this macro will transfer the schemars and serde's attributes\n        #[schemars(description = \"the left hand side number\")]\n        a: i32,\n        #[tool(param)]\n        #[schemars(description = \"the right hand side number\")]\n        b: i32,\n    ) -\u003e String {\n        (a - b).to_string()\n    }\n}\n\n// impl call_tool and list_tool by querying static toolbox\n#[tool(tool_box)]\nimpl ServerHandler for Calculator {\n    fn get_info(\u0026self) -\u003e ServerInfo {\n        ServerInfo {\n            instructions: Some(\"A simple calculator\".into()),\n            ..Default::default()\n        }\n    }\n}\n\n```\nThe only thing you should do is to make the function's return type implement `IntoCallToolResult`.\n\nAnd you can just implement `IntoContents`, and the return value will be marked as success automatically. \n\nIf you return a type of `Result\u003cT, E\u003e` where `T` and `E` both implemented `IntoContents`, it's also OK.\n\n### Manage Multi Services\nFor many cases you need to manage several service in a collection, you can call `into_dyn` to convert services into the same type.\n```rust, ignore\nlet service = service.into_dyn();\n```\n\n\n### Examples\nSee [examples](examples/README.md)\n\n### Features\n- `client`: use client side sdk\n- `server`: use server side sdk\n\n\n## Related Resources\n- [MCP Specification](https://spec.modelcontextprotocol.io/specification/2024-11-05/)\n\n- [Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.ts)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4t145%2Frmcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4t145%2Frmcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4t145%2Frmcp/lists"}