package client import ( "bytes" "context" "encoding/json" "io" "net/http" ) type rpcReq struct { JSONRPC string `json:"jsonrpc"` ID int `json:"id"` Method string `json:"method"` Params any `json:"params"` } type rpcResp struct { Result json.RawMessage `json:"result"` Error *struct { Message string `json:"message"` } `json:"error"` } func (c *Client) rpcCall(ctx context.Context, name string, args map[string]any) (json.RawMessage, error) { body, err := json.Marshal(rpcReq{ JSONRPC: "2.0", ID: 1, Method: "tools/call", Params: map[string]any{"name": name, "arguments": args}, }) if err != nil { return nil, ToolErrorf(name, "%w", err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.URL, bytes.NewReader(body)) if err != nil { return nil, ToolErrorf(name, "%w", err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json, text/event-stream") if c.Token != "" { req.Header.Set("Authorization", "Bearer "+c.Token) } httpClient := c.HTTP if httpClient == nil { httpClient = http.DefaultClient } resp, err := httpClient.Do(req) if err != nil { return nil, ToolErrorf(name, "%w", err) } defer resp.Body.Close() raw, err := io.ReadAll(resp.Body) if err != nil { return nil, ToolErrorf(name, "%w", err) } if resp.StatusCode >= 300 { return nil, ToolErrorf(name, "http %d: %s", resp.StatusCode, raw) } var out rpcResp if err := json.Unmarshal(raw, &out); err != nil { return nil, ToolErrorf(name, "%w", err) } if out.Error != nil { return nil, ToolErrorf(name, "%s", out.Error.Message) } return out.Result, nil }