diff --git a/contrib/codecs/http/client.go b/contrib/codecs/http/client.go
index 1937fa7b21fc88e20b74db9f30233026c4a079a8..301332e10357d6f4131516da023250f7b2d7d782 100644
--- a/contrib/codecs/http/client.go
+++ b/contrib/codecs/http/client.go
@@ -12,9 +12,10 @@ import (
 	"sync"
 	"sync/atomic"
 
+	"golang.org/x/net/http2"
+
 	"gfx.cafe/open/jrpc/pkg/jjson"
 	"gfx.cafe/open/jrpc/pkg/jsonrpc"
-	"golang.org/x/net/http2"
 )
 
 var (
diff --git a/contrib/extension/subscription/client.go b/contrib/extension/subscription/client.go
index 8b8f1361f838fc4409424e6563dbe71925c47f93..ac5a38e1911cf3e5338aed613dd31bf18f9041b1 100644
--- a/contrib/extension/subscription/client.go
+++ b/contrib/extension/subscription/client.go
@@ -172,8 +172,10 @@ func (c *clientSub) Unsubscribe() error {
 	c.engine.mu.Unlock()
 
 	// TODO: dont use context background here...
-	var result string
-	err := c.conn.Do(context.Background(), &result, c.namespace+serviceMethodSeparator+unsubscribeMethodSuffix, nil)
+	var result bool
+	err := c.conn.Do(context.Background(), &result, c.namespace+serviceMethodSeparator+unsubscribeMethodSuffix, []string{
+		c.id,
+	})
 	if err != nil {
 		return err
 	}
diff --git a/contrib/extension/subscription/client_test.go b/contrib/extension/subscription/client_test.go
index a1f9936f10c489720aebb24db657038eba54a0a2..4292e3be08f7dbe63589bb7aa22842cae7399d20 100644
--- a/contrib/extension/subscription/client_test.go
+++ b/contrib/extension/subscription/client_test.go
@@ -2,7 +2,6 @@ package subscription
 
 import (
 	"context"
-	"net/http"
 	"net/http/httptest"
 	_ "net/http/pprof"
 	"strings"
@@ -102,12 +101,6 @@ func TestUnsubscribeNoRead(t *testing.T) {
 }
 
 func TestWrapClient(t *testing.T) {
-	go func() {
-		if err := http.ListenAndServe(":6060", nil); err != nil {
-			panic(err)
-		}
-	}()
-
 	engine := NewEngine()
 	r := jmux.NewRouter()
 	r.Use(engine.Middleware())
diff --git a/contrib/extension/subscription/engine.go b/contrib/extension/subscription/engine.go
index e4ba9a25946bff45723bf187749b7adbe21f36c7..e8d1aa65999fbb2e83d400c67d1906817f255338 100644
--- a/contrib/extension/subscription/engine.go
+++ b/contrib/extension/subscription/engine.go
@@ -62,7 +62,7 @@ func (e *Engine) Middleware() func(jsonrpc.Handler) jsonrpc.Handler {
 				h.ServeRPC(w, r)
 			case strings.HasSuffix(r.Method, serviceMethodSeparator+unsubscribeMethodSuffix):
 				// read the subscription id to close
-				resp := []SubID{}
+				var resp []SubID
 				err := json.Unmarshal(r.Params, &resp)
 				if err != nil {
 					w.Send(false, err)
diff --git a/pkg/jsonrpc/json.go b/pkg/jsonrpc/json.go
index 30a1e0d37bbf9c366d303d3d3d7c4e7ee8246474..ba5bc5f201bafb99887ae8971556eea2cbfc1dba 100644
--- a/pkg/jsonrpc/json.go
+++ b/pkg/jsonrpc/json.go
@@ -223,7 +223,7 @@ func ReadMessage(dec *jx.Decoder) ([]*Message, bool) {
 		msgs = []*Message{}
 		dec.Arr(func(d *jx.Decoder) error {
 			msg := new(Message)
-			//err := UnmarshalMessage(msg, d)
+			// err := UnmarshalMessage(msg, d)
 			raw, err := d.Raw()
 			if err != nil {
 				raw = []byte{}
diff --git a/pkg/jsonrpc/reqresp.go b/pkg/jsonrpc/reqresp.go
index 3a4aedcf27da6151ebfb96861ab2072bb3ebcdac..67a5cbe7004547a1cadcd52a9093297730e43464 100644
--- a/pkg/jsonrpc/reqresp.go
+++ b/pkg/jsonrpc/reqresp.go
@@ -3,6 +3,8 @@ package jsonrpc
 import (
 	"context"
 	"encoding/json"
+
+	"github.com/go-faster/jx"
 )
 
 // http.ResponseWriter interface, but for jrpc
@@ -39,9 +41,12 @@ func NewRawRequest(ctx context.Context, id *ID, method string, params json.RawMe
 
 // NewRequest makes a new request
 func NewRequest(ctx context.Context, id *ID, method string, params any) (r *Request, err error) {
-	raw, err := json.Marshal(params)
-	if err != nil {
-		return nil, err
+	var raw json.RawMessage
+	if params != nil {
+		raw, err = json.Marshal(params)
+		if err != nil {
+			return nil, err
+		}
 	}
 	return NewRawRequest(ctx, id, method, raw), nil
 }
@@ -64,3 +69,24 @@ func (r *Request) WithContext(ctx context.Context) *Request {
 	r2.Peer = r.Peer
 	return r2
 }
+
+func (r Request) MarshalJSON() ([]byte, error) {
+	enc := jx.GetEncoder()
+	enc.Obj(func(e *jx.Encoder) {
+		e.FieldStart("jsonrpc")
+		e.Str(VersionString)
+		if r.ID != nil {
+			e.FieldStart("id")
+			e.Raw(*r.ID)
+		}
+		if r.Method != "" {
+			e.FieldStart("method")
+			e.Str(r.Method)
+		}
+		if r.Params != nil {
+			e.FieldStart("params")
+			e.Raw(r.Params)
+		}
+	})
+	return enc.Bytes(), nil
+}
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 0327b52280c3bf3b97d2d8b8da96b2c283ccf997..eb1aad99f44b77e5ec6798fdc75b0b52e5eff375 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -6,9 +6,10 @@ import (
 	"errors"
 	"sync"
 
+	"github.com/mailgun/multibuf"
+
 	"gfx.cafe/open/jrpc/pkg/jjson"
 	"gfx.cafe/open/jrpc/pkg/jsonrpc"
-	"github.com/mailgun/multibuf"
 )
 
 // Server is an RPC server.