A can grant cannot carry an authored description, so tool text is derived and near-identical across servers #58
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#58
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this is
describeis accepted inside aproxyblock but not inside acangrant.applyInlineGrantChildfails closed on anything outsidepath | query | body | set | fail-when, so a wrap-mode tool's description is always the derived string fromdescribe():Descriptor.Describeexists anddescribe()honours it — the field is simply unreachable from the wrap grammar.Why this is being raised now
coilyco-bridge/deploy#465builds five media servers on this runtime and names the tool surface as the whole craft of the work:That is not expressible. Two of the five are book servers (
deploy#468Open Library,deploy#469Gutendex), and the epic calls their overlap "the sharpest tool-naming risk in the batch." What ships is:search_book→ "Use this when the user wants to search book through the configured upstream service."get_readable_text→ "Use this when the user wants to get readable-text through the configured upstream service."Neither sentence rules the other tool out. The distinction survives only because Kai routed on the verb — lookup versus retrieval — which the names carry. That was a good call independently, and it is currently the only thing standing between those two servers and a model coin-flip.
The derived text is also visibly generic in practice: every Forgejo MCP tool in a live agent's context reads "Use this when the user wants to X through the configured upstream service," which tells a model nothing about scope, bounds, or when not to reach for it.
What would be enough
Accept
describeon acangrant, exactly asproxyalready does:Falling back to the derived string when absent keeps every existing guardfile working.
Note on scope
This is the more valuable of the two gaps I found — the other is
#57, rate limiting. Rate limiting bounds what these servers do to someone else's infrastructure; this one bounds whether the model picks the right tool at all, which is the difference between five servers and five servers that get used correctly.What I verified
Read against
mcp-beavermainandcli-guard v0.131.0on 2026-08-13, and confirmed empirically against derived descriptions in a live agent's loaded tool list. No deployed guardfile incoilyco-bridge/deployusesdescribeon a grant, so nothing depends on the current behaviour.This already works. Verified end to end against
mainand umbra v0.139.0, and pinned with tests in89f5a02.The issue was filed against cli-guard v0.131.0. The dependency is now umbra v0.139.0, and
describeis accepted on acangrant there:http/opcore/inline.go-applyInlineGrantControlChildhas acase "describe", and the fail-closed message readswant path | query | body | set | fail-when | describe.Descriptor.Describe(http/opcore/descriptor.go:25).describe()ininternal/mcpserver/server.goreturns it in preference to the derived string, which the issue correctly said was already true.So the field is reachable from the wrap grammar now. Three tests in
internal/mcpserver/describe_test.gocover the authored note reaching the served description, the derived fallback when absent, and fail-closed on an empty or duplicated note.Why no guardfile uses it is worth separating from whether it works. It is documented in
DESIGN.mdandFEATURES.md, but no example showed the shape, which is a good way for a feature to be invisible. Added a worked one toexamples/guardfile-siblings.mcp.kdl, written deliberately as the ruling-out sentence deploy#465 asks for:The two book servers can now say what they do not cover, so the distinction stops resting entirely on the verb routing.
Closing as already-delivered rather than as newly-built.