diff --git a/crates/graphicle/src/api.rs b/crates/graphicle/src/api.rs index 7487132..e13fdf5 100644 --- a/crates/graphicle/src/api.rs +++ b/crates/graphicle/src/api.rs @@ -2001,16 +2001,26 @@ fn mcp_in( } }) } - _ => Err(Error::bad("Unsupported MCP method")), + _ => Err(Error::bad(UNSUPPORTED_METHOD)), } })(); Some(match result { Ok(value) => json!({"jsonrpc":"2.0","id":request["id"],"result":value}), Err(error) => { - json!({"jsonrpc":"2.0","id":request["id"],"error":{"code":-32602,"message":error.message}}) + // JSON-RPC's "Method not found" for a method this connection + // does not serve, so that a client can tell it from a refused + // call. + let code = if error.message == UNSUPPORTED_METHOD { + -32601 + } else { + -32602 + }; + json!({"jsonrpc":"2.0","id":request["id"],"error":{"code":code,"message":error.message}}) } }) } +/// The error message of a method a connection does not serve. +const UNSUPPORTED_METHOD: &str = "Unsupported MCP method"; async fn mcp_http( State(app): State, Path((workspace, repository)): Path<(String, String)>, diff --git a/crates/graphicle/tests/it/workspace_scope.rs b/crates/graphicle/tests/it/workspace_scope.rs index 916c057..686023d 100644 --- a/crates/graphicle/tests/it/workspace_scope.rs +++ b/crates/graphicle/tests/it/workspace_scope.rs @@ -1256,6 +1256,11 @@ fn a_workspace_connection_serves_the_graph_tools_of_the_project_repo_names() { "Unsupported MCP method", "{refused}" ); + // JSON-RPC's "Method not found", not "Invalid params". + assert_eq!(refused["error"]["code"], -32601, "{refused}"); + // A refused call of a served method keeps "Invalid params". + let unknown_tool = rpc(&app, "tools/call", json!({"name":"no_such_tool"})); + assert_eq!(unknown_tool["error"]["code"], -32602, "{unknown_tool}"); // A navigation tool names its project, by id or key. let unnamed = call(&app, "get_node", json!({"label":"quantize_cents"})); assert!(