docs: show README content on docs.rs (#583)
Use `#![doc = include_str!("../README.md")]` to display README as crate
documentation on docs.rs for both `rmcp` and `rmcp-macros`.
Changes to support this:
- Fix code examples to compile as doc tests (`rust,no_run`)
- Fix broken rustdoc links with explicit `crate::` paths
- Add "Structured Output" section and examples link to rmcp README
- Simplify rmcp-macros README to a summary table with doc links
- Fix grammar throughout
- Add CSS to hide GitHub badges when rendered as rustdoc
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
acc1f8b525
commit
e623f2acab
2 changed files with 138 additions and 362 deletions
|
|
@ -1,208 +1,65 @@
|
|||
<style>
|
||||
.rustdoc-hidden { display: none; }
|
||||
</style>
|
||||
|
||||
<div class="rustdoc-hidden">
|
||||
|
||||
# rmcp-macros
|
||||
|
||||
[](https://crates.io/crates/rmcp-macros)
|
||||
[](https://docs.rs/rmcp-macros)
|
||||
|
||||
</div>
|
||||
|
||||
`rmcp-macros` is a procedural macro library for the Rust Model Context Protocol (RMCP) SDK, providing macros that facilitate the development of RMCP applications.
|
||||
|
||||
## Features
|
||||
## Available Macros
|
||||
|
||||
This library primarily provides the following macros:
|
||||
| Macro | Description |
|
||||
|-------|-------------|
|
||||
| [`#[tool]`][tool] | Mark a function as an MCP tool handler |
|
||||
| [`#[tool_router]`][tool_router] | Generate a tool router from an impl block |
|
||||
| [`#[tool_handler]`][tool_handler] | Generate `call_tool` and `list_tools` handler methods |
|
||||
| [`#[prompt]`][prompt] | Mark a function as an MCP prompt handler |
|
||||
| [`#[prompt_router]`][prompt_router] | Generate a prompt router from an impl block |
|
||||
| [`#[prompt_handler]`][prompt_handler] | Generate `get_prompt` and `list_prompts` handler methods |
|
||||
| [`#[task_handler]`][task_handler] | Wire up the task lifecycle on top of an `OperationProcessor` |
|
||||
|
||||
- `#[tool]`: Mark an async/sync function as an RMCP tool and generate metadata + schema glue
|
||||
- `#[tool_router]`: Collect all `#[tool]` functions in an impl block into a router value
|
||||
- `#[tool_handler]`: Implement the `call_tool` and `list_tools` entry points by delegating to a router expression
|
||||
- `#[task_handler]`: Wire up the task lifecycle (list/enqueue/get/cancel) on top of an `OperationProcessor`
|
||||
[tool]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.tool.html
|
||||
[tool_router]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.tool_router.html
|
||||
[tool_handler]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.tool_handler.html
|
||||
[prompt]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.prompt.html
|
||||
[prompt_router]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.prompt_router.html
|
||||
[prompt_handler]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.prompt_handler.html
|
||||
[task_handler]: https://docs.rs/rmcp-macros/latest/rmcp_macros/attr.task_handler.html
|
||||
|
||||
## Usage
|
||||
## Quick Example
|
||||
|
||||
### tool
|
||||
```rust,ignore
|
||||
use rmcp::{tool, tool_router, tool_handler, ServerHandler, model::*};
|
||||
|
||||
This macro is used to mark a function as a tool handler.
|
||||
|
||||
This will generate a function that return the attribute of this tool, with type `rmcp::model::Tool`.
|
||||
|
||||
#### Tool attributes
|
||||
|
||||
| field | type | usage |
|
||||
| :- | :- | :- |
|
||||
| `name` | `String` | The name of the tool. If not provided, it defaults to the function name. |
|
||||
| `description` | `String` | A description of the tool. The document of this function will be used. |
|
||||
| `input_schema` | `Expr` | A JSON Schema object defining the expected parameters for the tool. If not provide, if will use the json schema of its argument with type `Parameters<T>` |
|
||||
| `annotations` | `ToolAnnotationsAttribute` | Additional tool information. Defaults to `None`. |
|
||||
|
||||
#### Tool example
|
||||
|
||||
```rust
|
||||
#[tool(name = "my_tool", description = "This is my tool", annotations(title = "我的工具", read_only_hint = true))]
|
||||
pub async fn my_tool(param: Parameters<MyToolParam>) {
|
||||
// handling tool request
|
||||
}
|
||||
```
|
||||
|
||||
### tool_router
|
||||
|
||||
This macro is used to generate a tool router based on functions marked with `#[rmcp::tool]` in an implementation block.
|
||||
|
||||
It creates a function that returns a `ToolRouter` instance.
|
||||
|
||||
In most case, you need to add a field for handler to store the router information and initialize it when creating handler, or store it with a static variable.
|
||||
|
||||
#### Router attributes
|
||||
|
||||
| field | type | usage |
|
||||
| :- | :- | :- |
|
||||
| `router` | `Ident` | The name of the router function to be generated. Defaults to `tool_router`. |
|
||||
| `vis` | `Visibility` | The visibility of the generated router function. Defaults to empty. |
|
||||
|
||||
#### Router example
|
||||
|
||||
```rust
|
||||
#[tool_router]
|
||||
impl MyToolHandler {
|
||||
#[tool]
|
||||
pub fn my_tool() {
|
||||
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
// the default name of tool router will be `tool_router`
|
||||
tool_router: Self::tool_router(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or specify the visibility and router name, which would be helpful when you want to combine multiple routers into one:
|
||||
|
||||
```rust
|
||||
mod a {
|
||||
#[tool_router(router = tool_router_a, vis = "pub")]
|
||||
impl MyToolHandler {
|
||||
#[tool]
|
||||
fn my_tool_a() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod b {
|
||||
#[tool_router(router = tool_router_b, vis = "pub")]
|
||||
impl MyToolHandler {
|
||||
#[tool]
|
||||
fn my_tool_b() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MyToolHandler {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
tool_router: self::tool_router_a() + self::tool_router_b(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### tool_handler
|
||||
|
||||
This macro will generate the handler for `tool_call` and `list_tools` methods in the implementation block, by using an existing `ToolRouter` instance.
|
||||
|
||||
#### Handler attributes
|
||||
|
||||
| field | type | usage |
|
||||
| :- | :- | :- |
|
||||
| `router` | `Expr` | The expression to access the `ToolRouter` instance. Defaults to `self.tool_router`. |
|
||||
|
||||
#### Handler example
|
||||
|
||||
```rust
|
||||
#[tool_handler]
|
||||
impl ServerHandler for MyToolHandler {
|
||||
// ...implement other handler
|
||||
}
|
||||
```
|
||||
|
||||
or using a custom router expression:
|
||||
|
||||
```rust
|
||||
#[tool_handler(router = self.get_router().await)]
|
||||
impl ServerHandler for MyToolHandler {
|
||||
// ...implement other handler
|
||||
}
|
||||
```
|
||||
|
||||
#### Handler expansion
|
||||
|
||||
This macro will be expended to something like this:
|
||||
|
||||
```rust
|
||||
impl ServerHandler for MyToolHandler {
|
||||
async fn call_tool(
|
||||
&self,
|
||||
request: CallToolRequestParam,
|
||||
context: RequestContext<RoleServer>,
|
||||
) -> Result<CallToolResult, rmcp::ErrorData> {
|
||||
let tcc = ToolCallContext::new(self, request, context);
|
||||
self.tool_router.call(tcc).await
|
||||
}
|
||||
|
||||
async fn list_tools(
|
||||
&self,
|
||||
_request: Option<PaginatedRequestParam>,
|
||||
_context: RequestContext<RoleServer>,
|
||||
) -> Result<ListToolsResult, rmcp::ErrorData> {
|
||||
let items = self.tool_router.list_all();
|
||||
Ok(ListToolsResult::with_all_items(items))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### task_handler
|
||||
|
||||
This macro wires the task lifecycle endpoints (`list_tasks`, `enqueue_task`, `get_task`, `cancel_task`) to an implementation of `OperationProcessor`. It keeps the handler lean by delegating scheduling, status tracking, and cancellation semantics to the processor.
|
||||
|
||||
#### Task handler attributes
|
||||
|
||||
| field | type | usage |
|
||||
| :- | :- | :- |
|
||||
| `processor` | `Expr` | Expression that yields an `Arc<dyn OperationProcessor>` (or compatible trait object). Defaults to `self.processor.clone()`. |
|
||||
|
||||
#### Task handler example
|
||||
|
||||
```rust
|
||||
#[derive(Clone)]
|
||||
pub struct TaskHandler {
|
||||
processor: Arc<dyn OperationProcessor<RoleServer> + Send + Sync>,
|
||||
struct MyServer {
|
||||
tool_router: rmcp::handler::server::tool::ToolRouter<Self>,
|
||||
}
|
||||
|
||||
#[task_handler(processor = self.processor.clone())]
|
||||
impl ServerHandler for TaskHandler {}
|
||||
```
|
||||
|
||||
#### Task handler expansion
|
||||
|
||||
At expansion time the macro implements the task-specific handler methods by forwarding to the processor expression, roughly equivalent to:
|
||||
|
||||
```rust
|
||||
impl ServerHandler for TaskHandler {
|
||||
async fn list_tasks(&self, request: TaskListRequest, ctx: RequestContext<RoleServer>) -> Result<TaskListResult, rmcp::ErrorData> {
|
||||
self.processor.list_tasks(request, ctx).await
|
||||
#[tool_router]
|
||||
impl MyServer {
|
||||
#[tool(description = "Say hello")]
|
||||
async fn hello(&self) -> String {
|
||||
"Hello, world!".into()
|
||||
}
|
||||
}
|
||||
|
||||
async fn enqueue_task(&self, request: TaskEnqueueRequest, ctx: RequestContext<RoleServer>) -> Result<TaskEnqueueResult, rmcp::ErrorData> {
|
||||
self.processor.enqueue_task(request, ctx).await
|
||||
#[tool_handler]
|
||||
impl ServerHandler for MyServer {
|
||||
fn get_info(&self) -> ServerInfo {
|
||||
ServerInfo::default()
|
||||
}
|
||||
|
||||
// get_task and cancel_task are generated in the same manner.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Advanced Features
|
||||
|
||||
- Support for custom tool names and descriptions
|
||||
- Automatic generation of tool descriptions from documentation comments
|
||||
- JSON Schema generation for tool parameters
|
||||
See the [full documentation](https://docs.rs/rmcp-macros) for detailed usage of each macro.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue