Skip to main content

brainwires_network/client/
protocol.rs

1use brainwires_mcp::{JsonRpcRequest, JsonRpcResponse};
2use serde_json::{Value, json};
3
4use super::error::AgentNetworkClientError;
5
6/// Build a JSON-RPC initialize request with standard client info.
7pub fn build_initialize_request(id: u64) -> JsonRpcRequest {
8    JsonRpcRequest {
9        jsonrpc: "2.0".to_string(),
10        id: json!(id),
11        method: "initialize".to_string(),
12        params: Some(json!({
13            "protocolVersion": "2024-11-05",
14            "capabilities": {},
15            "clientInfo": {
16                "name": "brainwires-relay-client",
17                "version": "0.10.0"
18            }
19        })),
20    }
21}
22
23/// Build the initialized notification string to send after handshake.
24pub fn build_initialized_notification() -> String {
25    serde_json::to_string(&json!({
26        "jsonrpc": "2.0",
27        "method": "notifications/initialized"
28    }))
29    .expect("Failed to serialize initialized notification")
30}
31
32/// Build a JSON-RPC request to list available tools.
33pub fn build_tools_list_request(id: u64) -> JsonRpcRequest {
34    JsonRpcRequest {
35        jsonrpc: "2.0".to_string(),
36        id: json!(id),
37        method: "tools/list".to_string(),
38        params: None,
39    }
40}
41
42/// Build a JSON-RPC request to call a tool by name with arguments.
43pub fn build_tools_call_request(id: u64, name: &str, args: Value) -> JsonRpcRequest {
44    JsonRpcRequest {
45        jsonrpc: "2.0".to_string(),
46        id: json!(id),
47        method: "tools/call".to_string(),
48        params: Some(json!({
49            "name": name,
50            "arguments": args
51        })),
52    }
53}
54
55/// Parse a JSON-RPC response from a raw line of text.
56pub fn parse_response(line: &str) -> Result<JsonRpcResponse, AgentNetworkClientError> {
57    serde_json::from_str(line).map_err(|e| {
58        AgentNetworkClientError::Protocol(format!("Failed to parse response: {e}: {line}"))
59    })
60}
61
62/// Extract the result value from a JSON-RPC response, returning errors as needed.
63pub fn extract_result(response: JsonRpcResponse) -> Result<Value, AgentNetworkClientError> {
64    if let Some(error) = response.error {
65        return Err(AgentNetworkClientError::JsonRpc {
66            code: error.code,
67            message: error.message,
68        });
69    }
70    Ok(response.result.unwrap_or(json!(null)))
71}