1use std::fmt;
31
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
37pub enum McpMethod {
38 Initialize,
40 ListTools,
42 CallTool,
44 ListResources,
46 ReadResource,
48 ListPrompts,
50 GetPrompt,
52 Ping,
54 Unknown(String),
56}
57
58impl McpMethod {
59 #[must_use]
61 pub const fn as_str(&self) -> &str {
62 match self {
63 Self::Initialize => "initialize",
64 Self::ListTools => "tools/list",
65 Self::CallTool => "tools/call",
66 Self::ListResources => "resources/list",
67 Self::ReadResource => "resources/read",
68 Self::ListPrompts => "prompts/list",
69 Self::GetPrompt => "prompts/get",
70 Self::Ping => "ping",
71 Self::Unknown(s) => s.as_str(),
72 }
73 }
74
75 #[must_use]
77 #[allow(dead_code)] pub const fn is_known(&self) -> bool {
79 !matches!(self, Self::Unknown(_))
80 }
81
82 #[must_use]
84 #[allow(dead_code)] pub const fn known_methods() -> &'static [Self] {
86 &[
87 Self::Initialize,
88 Self::ListTools,
89 Self::CallTool,
90 Self::ListResources,
91 Self::ReadResource,
92 Self::ListPrompts,
93 Self::GetPrompt,
94 Self::Ping,
95 ]
96 }
97}
98
99impl From<&str> for McpMethod {
100 fn from(s: &str) -> Self {
101 match s {
102 "initialize" => Self::Initialize,
103 "tools/list" => Self::ListTools,
104 "tools/call" => Self::CallTool,
105 "resources/list" => Self::ListResources,
106 "resources/read" => Self::ReadResource,
107 "prompts/list" => Self::ListPrompts,
108 "prompts/get" => Self::GetPrompt,
109 "ping" => Self::Ping,
110 unknown => Self::Unknown(unknown.to_string()),
111 }
112 }
113}
114
115impl fmt::Display for McpMethod {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(f, "{}", self.as_str())
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_method_from_str() {
127 assert_eq!(McpMethod::from("initialize"), McpMethod::Initialize);
128 assert_eq!(McpMethod::from("tools/list"), McpMethod::ListTools);
129 assert_eq!(McpMethod::from("tools/call"), McpMethod::CallTool);
130 assert_eq!(McpMethod::from("resources/list"), McpMethod::ListResources);
131 assert_eq!(McpMethod::from("resources/read"), McpMethod::ReadResource);
132 assert_eq!(McpMethod::from("prompts/list"), McpMethod::ListPrompts);
133 assert_eq!(McpMethod::from("prompts/get"), McpMethod::GetPrompt);
134 assert_eq!(McpMethod::from("ping"), McpMethod::Ping);
135 }
136
137 #[test]
138 fn test_unknown_method() {
139 let method = McpMethod::from("unknown/method");
140 assert!(!method.is_known());
141 assert_eq!(method.as_str(), "unknown/method");
142 }
143
144 #[test]
145 fn test_method_as_str_roundtrip() {
146 for method in McpMethod::known_methods() {
147 let s = method.as_str();
148 let parsed = McpMethod::from(s);
149 assert_eq!(&parsed, method, "Roundtrip failed for {method}");
150 }
151 }
152
153 #[test]
154 fn test_method_display() {
155 assert_eq!(format!("{}", McpMethod::Initialize), "initialize");
156 assert_eq!(format!("{}", McpMethod::ListTools), "tools/list");
157 assert_eq!(format!("{}", McpMethod::Unknown("foo".to_string())), "foo");
158 }
159
160 #[test]
161 fn test_known_methods_count() {
162 assert_eq!(McpMethod::known_methods().len(), 8);
164 }
165
166 #[test]
167 fn test_all_known_methods_are_known() {
168 for method in McpMethod::known_methods() {
169 assert!(method.is_known(), "{method} should be known");
170 }
171 }
172}