///|
/// Custom errors for moonmcp, mirroring fastmcp/exceptions.py.
pub(all) suberror FastMCPError {
/// A wire-format protocol error, already carrying a JSON-RPC code.
Mcp(@types.ErrorData)
/// Error in validating parameters or return values.
Validation(String)
/// Error in resource operations.
Resource(String)
/// Error in tool operations.
Tool(String)
/// Error in prompt operations.
Prompt(String)
/// Invalid signature for use with moonmcp.
InvalidSignature(String)
/// Error in client operations.
Client(String)
/// Object not found.
NotFound(String)
/// Object is disabled.
Disabled(String)
/// A templated resource parameter failed path-security screening.
///
/// Surfaced to the client as an ordinary "not found" so a traversal
/// attempt is indistinguishable from a request for a missing resource.
ResourceSecurity(String)
/// Error when an authorisation check fails.
Authorisation(String)
/// Authorisation failed because the token is missing required scopes.
InsufficientScope(required_scopes~ : Array[String], message~ : String)
} derive(Debug, Eq)
///|
/// Construct an `InsufficientScope` error with the standard message.
pub fn insufficient_scope(required_scopes : Array[String]) -> FastMCPError {
let named = if required_scopes.is_empty() {
"(unknown)"
} else {
required_scopes.join(", ")
}
InsufficientScope(
required_scopes~,
message="Insufficient scope. Required: \{named}",
)
}
///|
/// Translate a moonmcp error into a wire-format error payload.
///
/// `NotFound`, `Disabled` and `Validation` map to `invalid_params` (-32602);
/// an existing `Mcp` payload is returned unchanged so an explicit code chosen
/// upstream survives translation; everything else falls back to
/// `default_code` (`internal_error` by default).
pub fn to_mcp_error(
exc : FastMCPError,
default_code~ : Int32 = @types.internal_error,
) -> @types.ErrorData {
match exc {
Mcp(data) => data
NotFound(message) | Disabled(message) | Validation(message) =>
{ code: @types.invalid_params, message, data: None, }
ResourceSecurity(message) =>
{ code: @types.invalid_params, message, data: None, }
_ => { code: default_code, message: exc.message(), data: None, }
}
}
///|
/// Render the human-readable message carried by the error.
pub fn FastMCPError::message(self : FastMCPError) -> String {
match self {
Mcp(data) => data.message
Validation(message)
| Resource(message)
| Tool(message)
| Prompt(message)
| InvalidSignature(message)
| Client(message)
| NotFound(message)
| Disabled(message)
| ResourceSecurity(message)
| Authorisation(message) => message
InsufficientScope(message~, ..) => message
}
}
///|
/// The message alone, as a person reads it.
pub impl Show for FastMCPError with fn output(self, logger) {
logger.write_string(self.message())
}
///|
pub extend FastMCPError with Show::{to_string, output}
///|
pub extend FastMCPError with Debug::{to_repr}
///|
pub extend FastMCPError with Eq::{not_equal, equal}