You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(macros): auto-generate get_info and default router (#785)
* feat(macros): auto-generate get_info and default router
* docs: simplify examples and docs with new defaults
* feat(macros): add tool_router(server_handler) to elide separate #[tool_handler] impl
* docs: add Tools section to README and simplify calculator examples with server_handler
Copy file name to clipboardExpand all lines: README.md
+71Lines changed: 71 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,7 @@ For the full MCP specification, see [modelcontextprotocol.io](https://modelconte
22
22
## Table of Contents
23
23
24
24
-[Usage](#usage)
25
+
-[Tools](#tools)
25
26
-[Resources](#resources)
26
27
-[Prompts](#prompts)
27
28
-[Sampling](#sampling)
@@ -129,6 +130,76 @@ let quit_reason = server.cancel().await?;
129
130
130
131
---
131
132
133
+
## Tools
134
+
135
+
Tools let servers expose callable functions to clients. Each tool has a name, description, and a JSON Schema for its parameters. Clients discover tools via `list_tools` and invoke them via `call_tool`.
The `#[tool]`, `#[tool_router]`, and `#[tool_handler]` macros handle all the wiring. For a tools-only server you can use `#[tool_router(server_handler)]` to skip the separate `ServerHandler` impl:
142
+
143
+
```rust,ignore
144
+
use rmcp::{tool, tool_router, ServiceExt, transport::stdio};
Resources let servers expose data (files, database records, API responses) that clients can read. Each resource is identified by a URI and returns content as text or binary (base64-encoded) data. Resource templates allow servers to declare URI patterns with dynamic parameters.
Copy file name to clipboardExpand all lines: crates/rmcp-macros/README.md
+22-9Lines changed: 22 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,7 @@ For **getting started** and **full MCP feature documentation**, see the [main RE
20
20
| Macro | Description |
21
21
|-------|-------------|
22
22
|[`#[tool]`][tool]| Mark a function as an MCP tool handler |
23
-
|[`#[tool_router]`][tool_router]| Generate a tool router from an impl block |
23
+
|[`#[tool_router]`][tool_router]| Generate a tool router from an impl block (optional `server_handler` flag elides a separate `#[tool_handler]` block for tools-only servers) |
24
24
|[`#[tool_handler]`][tool_handler]| Generate `call_tool` and `list_tools` handler methods |
25
25
|[`#[prompt]`][prompt]| Mark a function as an MCP prompt handler |
26
26
|[`#[prompt_router]`][prompt_router]| Generate a prompt router from an impl block |
@@ -37,13 +37,30 @@ For **getting started** and **full MCP feature documentation**, see the [main RE
37
37
38
38
## Quick Example
39
39
40
+
Tools-only server with a single `impl` block (`server_handler` expands `#[tool_handler]` in a second macro pass):
41
+
40
42
```rust,ignore
41
-
use rmcp::{tool, tool_router, tool_handler, ServerHandler, model::*};
If you need custom `#[tool_handler(...)]` arguments (e.g. `instructions`, `name`, or stacked `#[prompt_handler]` on the same `impl ServerHandler`), use two blocks instead:
58
+
59
+
```rust,ignore
60
+
use rmcp::{tool, tool_router, tool_handler, ServerHandler};
61
+
62
+
#[derive(Clone)]
63
+
struct MyServer;
47
64
48
65
#[tool_router]
49
66
impl MyServer {
@@ -54,11 +71,7 @@ impl MyServer {
54
71
}
55
72
56
73
#[tool_handler]
57
-
impl ServerHandler for MyServer {
58
-
fn get_info(&self) -> ServerInfo {
59
-
ServerInfo::default()
60
-
}
61
-
}
74
+
impl ServerHandler for MyServer {}
62
75
```
63
76
64
77
See the [full documentation](https://docs.rs/rmcp-macros) for detailed usage of each macro.
/// It creates a function that returns a `ToolRouter` instance.
49
49
///
50
-
/// 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.
50
+
/// The generated function is used by `#[tool_handler]` by default (via `Self::tool_router()`),
51
+
/// so in most cases you do not need to store the router in a field.
52
+
///
51
53
/// ## Usage
52
54
///
53
-
/// | field | type | usage |
54
-
/// | :- | :- | :- |
55
-
/// | `router` | `Ident` | The name of the router function to be generated. Defaults to `tool_router`. |
56
-
/// | `vis` | `Visibility` | The visibility of the generated router function. Defaults to empty. |
55
+
/// | field | type | usage |
56
+
/// | :- | :- | :- |
57
+
/// | `router` | `Ident` | The name of the router function to be generated. Defaults to `tool_router`. |
58
+
/// | `vis` | `Visibility` | The visibility of the generated router function. Defaults to empty. |
59
+
/// | `server_handler` | `flag` | When set, also emits `#[::rmcp::tool_handler]` on `impl ServerHandler for Self` so you can omit a separate `#[tool_handler]` block. |
/// This macro will generate the handler for `tool_call` and `list_tools` methods in the implementation block, by using an existing `ToolRouter` instance.
135
+
/// This macro generates the `call_tool`, `list_tools`, `get_tool`, and (optionally)
136
+
/// `get_info` methods for a `ServerHandler` implementation, using a `ToolRouter`.
118
137
///
119
138
/// ## Usage
120
139
///
121
-
/// | field | type | usage |
122
-
/// | :- | :- | :- |
123
-
/// | `router` | `Expr` | The expression to access the `ToolRouter` instance. Defaults to `self.tool_router`. |
124
-
/// ## Example
140
+
/// | field | type | usage |
141
+
/// | :- | :- | :- |
142
+
/// | `router` | `Expr` | The expression to access the `ToolRouter` instance. Defaults to `Self::tool_router()`. |
0 commit comments