`#[tool(description = …)]` accepts only a bare literal, while `#[doc]` and `#[schemars]` on the same items accept `include_str!` and `const` paths
维护者通常 3 天内回复
还没有人认领这个 Issue。
评估
调研方向
报告没有指出任何实现文件或测试;首先定位 #[tool] 属性解析器及其对 description 的验证。为 &'static str const 路径和 concat! 添加覆盖,保留字面量行为,并验证生成的 description 以及文档所述行为或错误行为与请求一致。
由索引模型根据 Issue 内容生成。
描述
Summary
description in #[tool] accepts only a bare string literal. Two attributes that sit on the very same items are more permissive: #[doc] on the function accepts include_str! and that value does reach the published description, and #[schemars(extend(…))] on the argument struct accepts const paths.
So a server can already source a tool's published text from outside the attribute — through #[doc], or through a literal handed in by a wrapper macro — just not through description, which is the field that names it. Accepting a const path and concat! there would remove the inconsistency.
This is an enhancement request, not a blocker: the workarounds below all work.
Version
rmcp 3.1.2, rustc 1.96.1, edition 2024.
What was measured
| form | result |
|---|---|
#[tool(description = "…")] |
works |
#[tool(description = my_crate::caps::TEXT)] |
error: Unexpected type \path`` |
#[tool(description = concat!("a", "b"))] |
error: Unexpected type \macro`` |
/// doc comment + #[tool] |
works — becomes the description |
#[doc = include_str!("text.md")] + #[tool] |
works — becomes the description |
#[schemars(extend("maximum" = MOST_STARTS_AT_ONCE))] on the args struct |
works — a const path, in the same attribute stack |
doc comment and description together |
description wins (no surprise here) |
macro_rules! wrapping the whole #[tool_router] impl |
works |
macro_rules! wrapping only the fn inside the impl |
compiles, registers nothing — filed separately |
The schemars row is the one that makes this feel like an oversight rather than a decision: a const is already acceptable one attribute away, for a value that is likewise baked into the published schema.
Why it matters on a larger surface
On a server with many tools the published text is an interface, and it usefully has two halves: a short one broadcast in tools/list before the first call, and a longer one fetched on demand. Ours measures 82 953 B of description across 66 tools, against a 13 590 B fetchable handbook — so keeping the split is worth real bytes, and it is far easier to keep the two halves honest when both can be declared together and the short one referenced from the attribute:
// what one would like to write
const GET_OR_CREATE_PROJECT: Capability = Capability {
broadcast: "…what prevents a wrong call…",
taught: "…the full explanation, fetched on demand…",
};
#[tool(description = GET_OR_CREATE_PROJECT.broadcast)]
Today that requires either moving the text into a file and using #[doc = include_str!(…)], or keeping a second copy plus a test comparing it to the literal.
Suggested change
Accept in description what neighbouring attributes already accept: a path to a const &'static str, and concat!. The generated code stores a &'static str either way.
If the literal is required because the value is needed during macro expansion, a line saying so in the docs — and an error message reading "only a string literal is accepted here" rather than naming the token type — would save the next person the experiment.
What this report does not establish
It does not claim the current behaviour is wrong, only that it is inconsistent with #[doc] and #[schemars] on the same items. name was not tested against a non-literal; only description was.
- 主要语言
- Rust
- 星标
- 4k
- 派生
- 654
- 平均合并
- 4 天 3 小时
- 30 天内合并 PR
- 40
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
modelcontextprotocol/rust-sdk 的其他 Issue
-
P3 question T-documentation T-enhancement
难度 1/5 1 小时以内 新手友好度 86/100
modelcontextprotocol/rust-sdk#1155 ·
维护者通常 3 天内回复
-
LocalSessionManager session workers don't cancel in-flight tool calls on client disconnect (follow-up to #857)可能已有人在做 @kkkhs 于 1 天前认领。 未关闭bug P1 ready for work T-transport
难度 4/5 3-5 天 新手友好度 55/100
modelcontextprotocol/rust-sdk#1325 ·
维护者通常 3 天内回复
-
streamable-http server: client responses to server-initiated requests (sampling/elicitation/roots) are 202-accepted and silently discarded under the 2026-07-28 protocol — the pending request hangs forever可能已有人在做 @DaleSeo 于 1 天前认领。 未关闭bug P1 ready for work T-transport
难度 5/5 一周以上 新手友好度 35/100
modelcontextprotocol/rust-sdk#1321 · 1 个 reaction · 已指派 1 人 ·
维护者通常 3 天内回复
-
Bound pre-lifecycle bootstrap attempts in server initialization可能已有人在做 @DaleSeo 于 5 天前认领。 未关闭enhancement P2 T-service T-transport
modelcontextprotocol/rust-sdk#1315 · 已指派 1 人 ·
维护者通常 3 天内回复
-
ProgressDispatcher: a slow progress subscriber blocks subscribe() and delivery for other tokens可能已有人在做 @monody0007 于 9 天前认领。 未关闭bug P1 ready for work T-handler
难度 4/5 3-5 天 新手友好度 25/100
modelcontextprotocol/rust-sdk#1312 ·
维护者通常 3 天内回复
查看 modelcontextprotocol/rust-sdk 的全部 Issue
相似的 Issue
-
agent:triaged bug bughunt pm:npm priority:p1
难度 2/5 1-3 小时 新手友好度 85/100
SocketDev/socket-patch#1127 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
-
documentation enhancement
难度 2/5 1-3 小时 新手友好度 62/100
adorsys/status-list-server#619 ·
维护者通常 2 天内回复
-
batch-backport only backports the first 30 matching PRs可能已有人在做 @DvirDukhan 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 5 天内回复
-
Configuration-level resource: `Allocate` rejects the kubelet's re-offer of the same device for a later container of the same Pod ("Unable to claim slot")可能已有人在做 @fang80913 于 38 天前认领。 未关闭bug
难度 2/5 1-3 小时 新手友好度 85/100
project-akri/akri#854 ·