Hmbown/CodeWhale · error · anyhow::Error
missing mcp__ prefix
Error message
missing mcp__ prefix
What it means
parse_qualified_tool_name() requires the string to start with the literal prefix 'mcp__'; the qualified format is mcp__<server>__<tool>. This bail (and the sibling 'missing server segment'/'missing tool segment' errors) means the caller passed a bare tool name, a server__tool pair without the prefix, or a name built by hand with the wrong shape.
Source
Thrown at crates/mcp/src/lib.rs:564
let remaining = component_budget - server_len - tool_len;
if remaining > 0 {
let server_extra = (server.len() - server_len).min(remaining);
server_len += server_extra;
tool_len += (tool.len() - tool_len).min(remaining - server_extra);
}
name = format!(
"mcp__{}__{}{}",
&server[..server_len],
&tool[..tool_len],
suffix
);
}
name
}
fn parse_qualified_tool_name(value: &str) -> Result<(String, String)> {
let Some(stripped) = value.strip_prefix("mcp__") else {
bail!("missing mcp__ prefix");
};
let mut split = stripped.splitn(2, "__");
let server = split
.next()
.filter(|s| !s.is_empty())
.map(ToOwned::to_owned)
.context("missing server segment")?;
let tool = split
.next()
.filter(|s| !s.is_empty())
.map(ToOwned::to_owned)
.context("missing tool segment")?;
Ok((server, tool))
}
#[derive(Debug, Deserialize)]
struct JsonRpcRequest {
#[serde(default)]View on GitHub (pinned to 0c42157ee5)
Solutions
- Prefix the name: pass mcp__<server>__<tool> with non-empty server and tool segments
- Build qualified names with the crate's formatting helper rather than manual concatenation
- For bare names, call call_tool(server, tool, args) directly instead of the qualified API
Example fix
// before
let v = registry.call_qualified_tool("github__search_code", args)?; // missing prefix
// after
let v = registry.call_qualified_tool("mcp__github__search_code", args)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_qualified_tool_name(s: &str) -> bool {
let Some(rest) = s.strip_prefix("mcp__") else { return false };
match rest.split_once("__") {
Some((server, tool)) => !server.is_empty() && !tool.is_empty(),
None => false,
}
}
if !is_qualified_tool_name(&name) { bail!("expected mcp__<server>__<tool>, got {name}"); } Type guard
fn split_qualified(s: &str) -> Option<(&str, &str)> {
s.strip_prefix("mcp__")?.split_once("__")
.filter(|(srv, tool)| !srv.is_empty() && !tool.is_empty())
} Prevention
- Validate the shape at the boundary where names enter (user input, LLM tool calls, config)
- Generate names with qualify-style helpers instead of string concatenation
- Use call_tool(server, tool) for bare names; reserve call_qualified_tool for genuinely qualified ones
When it happens
Trigger: Passing a bare tool name ('search_code') or 'github__search_code' to call_qualified_tool(); constructing qualified names by string concatenation instead of using the crate's qualify helper; stripping or lowercasing the prefix during logging/round-tripping so 'MCP__' or 'mcp_' no longer matches.
Common situations: Tool names round-tripped through user input, logs, or prompts where the prefix was trimmed; LLM-emitted tool calls missing the prefix; copy-paste between systems that use different qualification conventions.
Related errors
- qualified MCP tool name '{qualified_tool_name}' is ambiguous
- app-server auth token cannot be empty
- MCP server '{}' collides with already-registered server '{ex
- server '{server_name}' is not registered
- tool '{tool_name}' on MCP server '{server_name}' is blocked
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/b88e78b906749484.
Report an issue: GitHub.