agentox_core/checks/conformance/
unknown_method.rs1use crate::checks::runner::{Check, CheckContext};
4use crate::checks::types::{CheckCategory, CheckResult, Severity};
5use crate::protocol::jsonrpc::JsonRpcRequest;
6
7pub struct UnknownMethodHandling;
8
9const UNKNOWN_METHODS: &[&str] = &["nonexistent/method", "tools/nonexistent", "foo"];
10
11#[async_trait::async_trait]
12impl Check for UnknownMethodHandling {
13 fn id(&self) -> &str {
14 "CONF-006"
15 }
16
17 fn name(&self) -> &str {
18 "Unknown method handling"
19 }
20
21 fn category(&self) -> CheckCategory {
22 CheckCategory::Conformance
23 }
24
25 async fn run(&self, ctx: &mut CheckContext) -> Vec<CheckResult> {
26 let desc = "Server must return JSON-RPC error -32601 for unknown methods";
27 let mut results = Vec::new();
28
29 for method in UNKNOWN_METHODS {
30 let req =
31 JsonRpcRequest::new(ctx.session.next_id(), *method, Some(serde_json::json!({})));
32
33 match ctx.session.send_request(&req).await {
34 Ok(response) => {
35 if let Some(error) = &response.error {
36 if error.code != -32601 {
37 results.push(CheckResult::fail(
38 self.id(),
39 self.name(),
40 self.category(),
41 Severity::Medium,
42 desc,
43 format!(
44 "Method \"{method}\": expected error code -32601, got {}",
45 error.code
46 ),
47 ));
48 }
49 } else {
50 results.push(CheckResult::fail(
51 self.id(),
52 self.name(),
53 self.category(),
54 Severity::High,
55 desc,
56 format!(
57 "Method \"{method}\": server returned success instead of error"
58 ),
59 ));
60 }
61 }
62 Err(e) => {
63 results.push(CheckResult::fail(
64 self.id(),
65 self.name(),
66 self.category(),
67 Severity::High,
68 desc,
69 format!("Method \"{method}\": transport error: {e}"),
70 ));
71 }
72 }
73 }
74
75 if results.is_empty() {
76 results.push(CheckResult::pass(
77 self.id(),
78 self.name(),
79 self.category(),
80 desc,
81 ));
82 }
83
84 results
85 }
86}