diff --git a/benchmark/suite_test.go b/benchmark/suite_test.go
index e2829ad4c70952b5acabb817a55b029a68d25cf0..cd3767cff13231eb1f3d8a0157223a341c2c1ddd 100644
--- a/benchmark/suite_test.go
+++ b/benchmark/suite_test.go
@@ -7,8 +7,8 @@ import (
 	"gfx.cafe/open/jrpc/contrib/codecs/http"
 	"gfx.cafe/open/jrpc/contrib/codecs/rdwr"
 	"gfx.cafe/open/jrpc/contrib/codecs/websocket"
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -21,7 +21,7 @@ func TestBenchmarkSuite(t *testing.T) {
 	}
 
 	ctx := context.Background()
-	makeTest("SingleClient", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("SingleClient", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 		err := client.Do(ctx, nil, "test_ping", nil)
 		if err != nil {
 			t.Error(err)
@@ -37,7 +37,7 @@ func runBenchmarkSuite(b *testing.B, sm jrpctest.ServerMaker) {
 			executeBench(b, fm)
 		})
 	}
-	makeBench("SingleClient", func(b *testing.B, server *server.Server, client codec.Conn) {
+	makeBench("SingleClient", func(b *testing.B, server *server.Server, client jsonrpc.Conn) {
 		for i := 0; i < b.N; i++ {
 			err := client.Do(ctx, nil, "test_ping", nil)
 			if err != nil {
diff --git a/contrib/client/pooling.go b/contrib/client/pooling.go
index dea11946e46f39053dd26e16105297505e17db08..cc9c210e12981ba1512185bf13b0134d5d88636f 100644
--- a/contrib/client/pooling.go
+++ b/contrib/client/pooling.go
@@ -8,18 +8,18 @@ import (
 
 	"gfx.cafe/open/jrpc"
 	"gfx.cafe/open/jrpc/contrib/extension/subscription"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
-var _ codec.Conn = (*Pooling)(nil)
+var _ jsonrpc.Conn = (*Pooling)(nil)
 var _ subscription.Conn = (*Pooling)(nil)
 
 type Pooling struct {
 	dialer     func(ctx context.Context) (jrpc.Conn, error)
-	conns      chan codec.Conn
+	conns      chan jsonrpc.Conn
 	base       subscription.Conn
 	closed     atomic.Bool
-	middleware []codec.Middleware
+	middleware []jsonrpc.Middleware
 
 	mu sync.Mutex
 }
@@ -56,7 +56,7 @@ func (p *Pooling) Subscribe(ctx context.Context, namespace string, channel any,
 func NewPooling(ctx context.Context, dialer func(ctx context.Context) (jrpc.Conn, error), max int) (*Pooling, error) {
 	r := &Pooling{
 		dialer: dialer,
-		conns:  make(chan codec.Conn, max),
+		conns:  make(chan jsonrpc.Conn, max),
 	}
 
 	return r, nil
@@ -79,7 +79,7 @@ func (r *Pooling) Do(ctx context.Context, result any, method string, params any)
 	return <-errChan
 }
 
-func (r *Pooling) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
+func (r *Pooling) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
 	if r.closed.Load() {
 		return net.ErrClosed
 	}
@@ -96,7 +96,7 @@ func (r *Pooling) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
 	return <-errChan
 }
 
-func (p *Pooling) Mount(m codec.Middleware) {
+func (p *Pooling) Mount(m jsonrpc.Middleware) {
 	p.middleware = append(p.middleware, m)
 }
 
diff --git a/contrib/client/reconnecting.go b/contrib/client/reconnecting.go
index 3191538ce6cd4d6f2f64beadd27faa4b4e018f0a..162df40c0790c51c99b09a897bed0d8c03a40cd9 100644
--- a/contrib/client/reconnecting.go
+++ b/contrib/client/reconnecting.go
@@ -5,16 +5,16 @@ import (
 	"sync"
 
 	"gfx.cafe/open/jrpc"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 var _ jrpc.StreamingConn = (*Reconnecting)(nil)
 
 type Reconnecting struct {
 	dialer     func(ctx context.Context) (jrpc.StreamingConn, error)
-	base       codec.StreamingConn
+	base       jsonrpc.StreamingConn
 	alive      bool
-	middleware []codec.Middleware
+	middleware []jsonrpc.Middleware
 
 	mu sync.Mutex
 }
@@ -73,7 +73,7 @@ func (r *Reconnecting) Do(ctx context.Context, result any, method string, params
 	return <-errChan
 }
 
-func (r *Reconnecting) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
+func (r *Reconnecting) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
 	errChan := make(chan error)
 	go func() {
 		conn, err := r.getClient(ctx)
@@ -86,7 +86,7 @@ func (r *Reconnecting) BatchCall(ctx context.Context, b ...*codec.BatchElem) err
 	return <-errChan
 }
 
-func (r *Reconnecting) Mount(m codec.Middleware) {
+func (r *Reconnecting) Mount(m jsonrpc.Middleware) {
 	r.middleware = append(r.middleware, m)
 }
 
diff --git a/contrib/codecs/_broker/client.go b/contrib/codecs/_broker/client.go
index 6ccfbc39768bcb2be90260aa65ea0484a3b324dc..9c41206547c5b4916b18ace7ecbd1bc8a41f79ac 100644
--- a/contrib/codecs/_broker/client.go
+++ b/contrib/codecs/_broker/client.go
@@ -7,7 +7,7 @@ import (
 	"sync"
 
 	"gfx.cafe/open/jrpc/pkg/clientutil"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"github.com/rs/xid"
 )
 
@@ -20,24 +20,24 @@ type Client struct {
 	ctx context.Context
 	cn  context.CancelFunc
 
-	m       codec.Middlewares
-	handler codec.Handler
+	m       jsonrpc.Middlewares
+	handler jsonrpc.Handler
 	mu      sync.RWMutex
 
-	handlerPeer codec.PeerInfo
+	handlerPeer jsonrpc.PeerInfo
 }
 
 func NewClient(spoke ClientSpoke) *Client {
 	cl := &Client{
 		c: spoke,
 		p: clientutil.NewIdReply(),
-		handlerPeer: codec.PeerInfo{
+		handlerPeer: jsonrpc.PeerInfo{
 			Transport:  "broker",
 			RemoteAddr: "",
 		},
 		// this doesn't need to be secure bc... you have access to the redis instance lol
 		clientId: xid.New().String(),
-		handler:  codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {}),
+		handler:  jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {}),
 	}
 	cl.ctx, cl.cn = context.WithCancel(context.Background())
 	go cl.listen()
@@ -48,15 +48,15 @@ func (c *Client) Closed() <-chan struct{} {
 	return c.ctx.Done()
 }
 
-func (c *Client) SetHandlerPeer(pi codec.PeerInfo) {
+func (c *Client) SetHandlerPeer(pi jsonrpc.PeerInfo) {
 	c.handlerPeer = pi
 }
 
-func (c *Client) Mount(h codec.Middleware) {
+func (c *Client) Mount(h jsonrpc.Middleware) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	c.m = append(c.m, h)
-	c.handler = c.m.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+	c.handler = c.m.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		// do nothing on no handler
 	})
 }
@@ -75,7 +75,7 @@ func (c *Client) listen() error {
 		case <-c.ctx.Done():
 			return c.ctx.Err()
 		}
-		msgs, _ := codec.ParseMessage(incomingMsg)
+		msgs, _ := jsonrpc.ParseMessage(incomingMsg)
 		for i := range msgs {
 			v := msgs[i]
 			if v == nil {
@@ -84,14 +84,14 @@ func (c *Client) listen() error {
 			id := v.ID
 			//  messages without ids are notifications
 			if id == nil {
-				var handler codec.Handler
+				var handler jsonrpc.Handler
 				c.mu.RLock()
 				handler = c.handler
 				c.mu.RUnlock()
 				// writer should only be allowed to send notifications
 				// reader should contain the message above
 				// the context is the client context
-				req := codec.NewRawRequest(c.ctx,
+				req := jsonrpc.NewRawRequest(c.ctx,
 					nil,
 					v.Method,
 					v.Params,
@@ -112,7 +112,7 @@ func (c *Client) listen() error {
 
 func (c *Client) Do(ctx context.Context, result any, method string, params any) error {
 	id := c.p.NextId()
-	req, err := codec.NewRequest(ctx, codec.NewId(id), method, params)
+	req, err := jsonrpc.NewRequest(ctx, jsonrpc.NewId(id), method, params)
 	if err != nil {
 		return err
 	}
@@ -137,17 +137,17 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any)
 	return nil
 }
 
-func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
+func (c *Client) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
 	if ctx == nil {
 		ctx = context.Background()
 	}
 	buf := new(bytes.Buffer)
 	enc := json.NewEncoder(buf)
-	reqs := make([]*codec.Request, 0, len(b))
-	ids := make([]*codec.ID, 0, len(b))
+	reqs := make([]*jsonrpc.Request, 0, len(b))
+	ids := make([]*jsonrpc.ID, 0, len(b))
 	for _, v := range b {
 		id := c.p.NextId()
-		req, err := codec.NewRequest(ctx, codec.NewId(id), v.Method, v.Params)
+		req, err := jsonrpc.NewRequest(ctx, jsonrpc.NewId(id), v.Method, v.Params)
 		if err != nil {
 			return err
 		}
@@ -191,7 +191,7 @@ func (c *Client) Notify(ctx context.Context, method string, params any) error {
 	if ctx == nil {
 		ctx = context.Background()
 	}
-	req, err := codec.NewRequest(ctx, nil, method, params)
+	req, err := jsonrpc.NewRequest(ctx, nil, method, params)
 	if err != nil {
 		return err
 	}
diff --git a/contrib/codecs/_broker/codec.go b/contrib/codecs/_broker/codec.go
index adac8b6ee10592e8207f3ef8d6c3d5732f59ec4c..7a59323a0166054ad84e521124ef106a6abb629f 100644
--- a/contrib/codecs/_broker/codec.go
+++ b/contrib/codecs/_broker/codec.go
@@ -6,12 +6,12 @@ import (
 	"encoding/json"
 	"sync/atomic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/serverutil"
 	"github.com/gogo/protobuf/io"
 )
 
-var _ codec.ReaderWriter = (*Codec)(nil)
+var _ jsonrpc.ReaderWriter = (*Codec)(nil)
 
 type Codec struct {
 	ctx context.Context
@@ -23,7 +23,7 @@ type Codec struct {
 	closed  atomic.Bool
 	closeCh chan struct{}
 
-	i codec.PeerInfo
+	i jsonrpc.PeerInfo
 }
 
 type httpError struct {
@@ -44,11 +44,11 @@ func NewCodec(req json.RawMessage, replier Replier) *Codec {
 }
 
 // gets the peer info
-func (c *Codec) PeerInfo() codec.PeerInfo {
+func (c *Codec) PeerInfo() jsonrpc.PeerInfo {
 	return c.i
 }
 
-func (c *Codec) ReadBatch(ctx context.Context) ([]*codec.Message, bool, error) {
+func (c *Codec) ReadBatch(ctx context.Context) ([]*jsonrpc.Message, bool, error) {
 	select {
 	case ans := <-c.ansCh:
 		return ans.Messages, ans.Batch, nil
diff --git a/contrib/codecs/_broker/codec_test.go b/contrib/codecs/_broker/codec_test.go
index 66e02f06d37737587f578720119cf4a17a3e8dfe..077a492814c118cfaa1dbd7a4fbd4503a4724300 100644
--- a/contrib/codecs/_broker/codec_test.go
+++ b/contrib/codecs/_broker/codec_test.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"testing"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
@@ -18,7 +18,7 @@ func TestBasicSuite(t *testing.T) {
 			s := jrpctest.NewServer()
 			spokeServer := (&Server{Server: s})
 			go spokeServer.ServeSpoke(ctx, broker)
-			return s, func() codec.Conn {
+			return s, func() jsonrpc.Conn {
 					conn := NewClient(broker)
 					return conn
 				}, func() {
diff --git a/contrib/codecs/dialer.go b/contrib/codecs/dialer.go
index 7e010c1e9606f1e84cbaed8d51ec9181d1e35545..59caf186b6bb27b3da5315c37249b3369f463179 100644
--- a/contrib/codecs/dialer.go
+++ b/contrib/codecs/dialer.go
@@ -6,12 +6,12 @@ import (
 	"fmt"
 	"net/url"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 var ErrSchemeNotSupported = errors.New("url scheme not supported")
 
-func DialContext(ctx context.Context, u string) (codec.Conn, error) {
+func DialContext(ctx context.Context, u string) (jsonrpc.Conn, error) {
 	pu, err := url.Parse(u)
 	if err != nil {
 		return nil, err
@@ -23,7 +23,7 @@ func DialContext(ctx context.Context, u string) (codec.Conn, error) {
 	return dialer(ctx, u)
 }
 
-func Dial(u string) (codec.Conn, error) {
+func Dial(u string) (jsonrpc.Conn, error) {
 	ctx := context.Background()
 	return DialContext(ctx, u)
 }
diff --git a/contrib/codecs/http/client.go b/contrib/codecs/http/client.go
index 24d1d7a1790a99281de206dd074437e6a70bc857..95fb6f169bfe8a4bdb4969c6f4832c2bfc39236c 100644
--- a/contrib/codecs/http/client.go
+++ b/contrib/codecs/http/client.go
@@ -11,7 +11,7 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 
 	"gfx.cafe/util/go/bufpool"
 
@@ -26,7 +26,7 @@ var (
 	errDead                      = errors.New("connection lost")
 )
 
-var _ codec.Conn = (*Client)(nil)
+var _ jsonrpc.Conn = (*Client)(nil)
 
 // Client represents a connection to an RPC server.
 type Client struct {
@@ -37,16 +37,16 @@ type Client struct {
 
 	headers http.Header
 
-	m       codec.Middlewares
-	handler codec.Handler
+	m       jsonrpc.Middlewares
+	handler jsonrpc.Handler
 	mu      sync.RWMutex
 }
 
-func (c *Client) Mount(h codec.Middleware) {
+func (c *Client) Mount(h jsonrpc.Middleware) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	c.m = append(c.m, h)
-	c.handler = c.m.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+	c.handler = c.m.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		// do nothing on no handler
 	})
 }
@@ -71,7 +71,7 @@ func (c *Client) SetHeader(key string, value string) {
 }
 
 func (c *Client) Do(ctx context.Context, result any, method string, params any) error {
-	req, err := codec.NewRequest(ctx, codec.NewId(c.id.Add(1)), method, params)
+	req, err := jsonrpc.NewRequest(ctx, jsonrpc.NewId(c.id.Add(1)), method, params)
 	if err != nil {
 		return err
 	}
@@ -82,7 +82,7 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any)
 	defer resp.Body.Close()
 	if resp.StatusCode != 200 {
 		b, _ := io.ReadAll(resp.Body)
-		return &codec.HTTPError{
+		return &jsonrpc.HTTPError{
 			StatusCode: resp.StatusCode,
 			Status:     resp.Status,
 			Body:       b,
@@ -108,7 +108,7 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any)
 }
 
 func (c *Client) Notify(ctx context.Context, method string, params any) error {
-	req, err := codec.NewRequest(ctx, nil, method, params)
+	req, err := jsonrpc.NewRequest(ctx, nil, method, params)
 	if err != nil {
 		return err
 	}
@@ -120,18 +120,18 @@ func (c *Client) Notify(ctx context.Context, method string, params any) error {
 	return err
 }
 
-func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
-	reqs := make([]*codec.Request, len(b))
+func (c *Client) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
+	reqs := make([]*jsonrpc.Request, len(b))
 	ids := make(map[int]int, len(b))
 	for idx, v := range b {
-		var rid *codec.ID
+		var rid *jsonrpc.ID
 		if v.IsNotification {
 		} else {
 			id := int(c.id.Add(1))
 			ids[idx] = id
-			rid = codec.NewNumberIDPtr(int64(id))
+			rid = jsonrpc.NewNumberIDPtr(int64(id))
 		}
-		req, err := codec.NewRequest(ctx, rid, v.Method, v.Params)
+		req, err := jsonrpc.NewRequest(ctx, rid, v.Method, v.Params)
 		if err != nil {
 			return err
 		}
@@ -147,7 +147,7 @@ func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
 	}
 	defer resp.Body.Close()
 
-	msgs := []*codec.Message{}
+	msgs := []*jsonrpc.Message{}
 	err = json.NewDecoder(resp.Body).Decode(&msgs)
 	if err != nil {
 		return err
@@ -164,7 +164,7 @@ func (c *Client) Closed() <-chan struct{} {
 	return make(chan struct{})
 }
 
-func (c *Client) post(req *codec.Request) (*http.Response, error) {
+func (c *Client) post(req *jsonrpc.Request) (*http.Response, error) {
 	// TODO: use buffer for this
 	buf := bufpool.GetStd()
 	defer bufpool.PutStd(buf)
diff --git a/contrib/codecs/http/codec.go b/contrib/codecs/http/codec.go
index 3a8e68066cd0483a77f07e407139dad074cba402..cd84c8bc0ffb4376f8ab53f0d2047b19dc157682 100644
--- a/contrib/codecs/http/codec.go
+++ b/contrib/codecs/http/codec.go
@@ -13,11 +13,11 @@ import (
 	"strings"
 	"sync"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/serverutil"
 )
 
-var _ codec.ReaderWriter = (*Codec)(nil)
+var _ jsonrpc.ReaderWriter = (*Codec)(nil)
 
 // Reusable codec. use Reset()
 type Codec struct {
@@ -32,7 +32,7 @@ type Codec struct {
 
 	mu sync.Mutex
 
-	i codec.PeerInfo
+	i jsonrpc.PeerInfo
 }
 
 type httpError struct {
@@ -65,7 +65,7 @@ func (c *Codec) Reset(w http.ResponseWriter, r *http.Request) {
 func (c *Codec) peerInfo() {
 	c.i.Transport = "http"
 	c.i.RemoteAddr = c.r.RemoteAddr
-	c.i.HTTP = codec.HttpInfo{
+	c.i.HTTP = jsonrpc.HttpInfo{
 		Version:   c.r.Proto,
 		UserAgent: c.r.UserAgent(),
 		Host:      c.r.Host,
@@ -84,7 +84,7 @@ func (c *Codec) peerInfo() {
 }
 
 // gets the peer info
-func (c *Codec) PeerInfo() codec.PeerInfo {
+func (c *Codec) PeerInfo() jsonrpc.PeerInfo {
 	return c.i
 }
 
@@ -103,8 +103,8 @@ func (r *Codec) doReadGet() (msg *serverutil.Bundle, err error) {
 		id = "1"
 	}
 	return &serverutil.Bundle{
-		Messages: []*codec.Message{{
-			ID:     codec.NewId(id),
+		Messages: []*jsonrpc.Message{{
+			ID:     jsonrpc.NewId(id),
 			Method: method_up,
 			Params: param,
 		}},
@@ -126,8 +126,8 @@ func (r *Codec) doReadRPC() (msg *serverutil.Bundle, err error) {
 		return nil, err
 	}
 	return &serverutil.Bundle{
-		Messages: []*codec.Message{{
-			ID:     codec.NewId(id),
+		Messages: []*jsonrpc.Message{{
+			ID:     jsonrpc.NewId(id),
 			Method: method_up,
 			Params: data,
 		}},
@@ -202,7 +202,7 @@ func (c *Codec) doRead() {
 	}()
 }
 
-func (c *Codec) ReadBatch(ctx context.Context) ([]*codec.Message, bool, error) {
+func (c *Codec) ReadBatch(ctx context.Context) ([]*jsonrpc.Message, bool, error) {
 	select {
 	case ans := <-c.msgs:
 		return ans.Messages, ans.Batch, nil
diff --git a/contrib/codecs/http/http_test.go b/contrib/codecs/http/http_test.go
index b8e5c78f0feae7022af0b72a32aac4f1237d1cbb..a73fd139e709f7bcd2794274426af0dc6a961f34 100644
--- a/contrib/codecs/http/http_test.go
+++ b/contrib/codecs/http/http_test.go
@@ -26,7 +26,7 @@ import (
 
 	"gfx.cafe/open/jrpc"
 	"gfx.cafe/open/jrpc/contrib/jmux"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
@@ -156,7 +156,7 @@ func TestHTTPErrorResponse(t *testing.T) {
 		t.Fatal("error was expected")
 	}
 
-	httpErr, ok := err.(*codec.HTTPError)
+	httpErr, ok := err.(*jsonrpc.HTTPError)
 	if !ok {
 		t.Fatalf("unexpected error type %T", err)
 	}
@@ -189,7 +189,7 @@ func TestHTTPPeerInfo(t *testing.T) {
 	c.SetHeader("x-forwarded-for", "origin.example.com")
 
 	// Request peer information.
-	var info codec.PeerInfo
+	var info jsonrpc.PeerInfo
 	if err := c.Do(nil, &info, "test_peerInfo", nil); err != nil {
 		t.Fatal(err)
 	}
diff --git a/contrib/codecs/http/testing.go b/contrib/codecs/http/testing.go
index 7c91c4fdac33936bcb183978b772bea9fd0e74de..aa708c7eda0873b007fb732eb1eb93e4cc3247ab 100644
--- a/contrib/codecs/http/testing.go
+++ b/contrib/codecs/http/testing.go
@@ -3,15 +3,15 @@ package http
 import (
 	"net/http/httptest"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
 func ServerMaker() (*server.Server, jrpctest.ClientMaker, func()) {
 	s := jrpctest.NewServer()
 	hsrv := httptest.NewServer(&Server{Server: s})
-	return s, func() codec.Conn {
+	return s, func() jsonrpc.Conn {
 		conn, err := DialHTTP(hsrv.URL)
 		if err != nil {
 			panic(err)
diff --git a/contrib/codecs/init.go b/contrib/codecs/init.go
index 4c6db9431fffd5bc9a6a7f36316c1f407b2a5695..6b6658cdc606b03a8f3044454063882607f04d75 100644
--- a/contrib/codecs/init.go
+++ b/contrib/codecs/init.go
@@ -10,7 +10,7 @@ import (
 	"gfx.cafe/open/jrpc/contrib/codecs/http"
 	"gfx.cafe/open/jrpc/contrib/codecs/rdwr"
 	"gfx.cafe/open/jrpc/contrib/codecs/websocket"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -49,14 +49,14 @@ func init() {
 	RegisterHandler(func(bind *url.URL, srv *server.Server, opts map[string]any) error {
 		return gohttp.ListenAndServe(bind.Host, HttpHandler(srv))
 	}, "http")
-	RegisterDialer(func(ctx context.Context, url string) (codec.Conn, error) {
+	RegisterDialer(func(ctx context.Context, url string) (jsonrpc.Conn, error) {
 		return http.Dial(ctx, nil, url)
 	}, "https", "http")
-	RegisterDialer(func(ctx context.Context, url string) (codec.Conn, error) {
+	RegisterDialer(func(ctx context.Context, url string) (jsonrpc.Conn, error) {
 		return websocket.DialWebsocket(ctx, url, "")
 	}, "wss", "ws")
 
-	RegisterDialer(func(ctx context.Context, url string) (codec.Conn, error) {
+	RegisterDialer(func(ctx context.Context, url string) (jsonrpc.Conn, error) {
 		tcpAddr, err := net.ResolveTCPAddr("tcp", url)
 		if err != nil {
 			return nil, err
diff --git a/contrib/codecs/rdwr/client.go b/contrib/codecs/rdwr/client.go
index 6224631f75b0e4bbb270033d34edbba4e3be94f0..3cf36f6b18a2a93630e2e66b5de1f8535966f461 100644
--- a/contrib/codecs/rdwr/client.go
+++ b/contrib/codecs/rdwr/client.go
@@ -8,7 +8,7 @@ import (
 	"sync"
 
 	"gfx.cafe/open/jrpc/pkg/clientutil"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/util/go/bufpool"
 )
 
@@ -21,13 +21,13 @@ type Client struct {
 	ctx context.Context
 	cn  context.CancelFunc
 
-	m       codec.Middlewares
-	handler codec.Handler
+	m       jsonrpc.Middlewares
+	handler jsonrpc.Handler
 	writeCh chan struct{}
 
 	mu sync.RWMutex
 
-	handlerPeer codec.PeerInfo
+	handlerPeer jsonrpc.PeerInfo
 }
 
 func NewClient(rd io.Reader, wr io.Writer) *Client {
@@ -35,11 +35,11 @@ func NewClient(rd io.Reader, wr io.Writer) *Client {
 		p:  clientutil.NewIdReply(),
 		rd: bufio.NewReader(rd),
 		wr: wr,
-		handlerPeer: codec.PeerInfo{
+		handlerPeer: jsonrpc.PeerInfo{
 			Transport:  "ipc",
 			RemoteAddr: "",
 		},
-		handler: codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {}),
+		handler: jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {}),
 		writeCh: make(chan struct{}, 1),
 	}
 	cl.ctx, cl.cn = context.WithCancel(context.Background())
@@ -47,7 +47,7 @@ func NewClient(rd io.Reader, wr io.Writer) *Client {
 	return cl
 }
 
-func (c *Client) SetHandlerPeer(pi codec.PeerInfo) {
+func (c *Client) SetHandlerPeer(pi jsonrpc.PeerInfo) {
 	c.handlerPeer = pi
 }
 
@@ -55,11 +55,11 @@ func (c *Client) Closed() <-chan struct{} {
 	return c.ctx.Done()
 }
 
-func (c *Client) Mount(h codec.Middleware) {
+func (c *Client) Mount(h jsonrpc.Middleware) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	c.m = append(c.m, h)
-	c.handler = c.m.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+	c.handler = c.m.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		// do nothing on no handler
 	})
 }
@@ -73,7 +73,7 @@ func (c *Client) listen() error {
 		if err != nil {
 			return err
 		}
-		msgs, _ := codec.ParseMessage(msg)
+		msgs, _ := jsonrpc.ParseMessage(msg)
 		for i := range msgs {
 			v := msgs[i]
 			if v == nil {
@@ -82,14 +82,14 @@ func (c *Client) listen() error {
 			id := v.ID
 			//  messages without ids are notifications
 			if id == nil {
-				var handler codec.Handler
+				var handler jsonrpc.Handler
 				c.mu.RLock()
 				handler = c.handler
 				c.mu.RUnlock()
 				// writer should only be allowed to send notifications
 				// reader should contain the message above
 				// the context is the client context
-				req := codec.NewRawRequest(c.ctx,
+				req := jsonrpc.NewRawRequest(c.ctx,
 					nil,
 					v.Method,
 					v.Params,
@@ -112,7 +112,7 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any)
 	id := c.p.NextId()
 	buf := bufpool.GetStd()
 	defer bufpool.PutStd(buf)
-	req, err := codec.NewRequest(ctx, codec.NewId(id), method, params)
+	req, err := jsonrpc.NewRequest(ctx, jsonrpc.NewId(id), method, params)
 	if err != nil {
 		return err
 	}
@@ -137,18 +137,18 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any)
 	return nil
 }
 
-func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
+func (c *Client) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
 	if ctx == nil {
 		ctx = context.Background()
 	}
 	buf := bufpool.GetStd()
 	defer bufpool.PutStd(buf)
 	enc := json.NewEncoder(buf)
-	reqs := make([]*codec.Request, 0, len(b))
-	ids := make([]*codec.ID, 0, len(b))
+	reqs := make([]*jsonrpc.Request, 0, len(b))
+	ids := make([]*jsonrpc.ID, 0, len(b))
 	for _, v := range b {
 		id := c.p.NextId()
-		req, err := codec.NewRequest(ctx, codec.NewId(id), v.Method, v.Params)
+		req, err := jsonrpc.NewRequest(ctx, jsonrpc.NewId(id), v.Method, v.Params)
 		if err != nil {
 			return err
 		}
@@ -192,7 +192,7 @@ func (c *Client) Notify(ctx context.Context, method string, params any) error {
 	if ctx == nil {
 		ctx = context.Background()
 	}
-	req, err := codec.NewRequest(ctx, nil, method, params)
+	req, err := jsonrpc.NewRequest(ctx, nil, method, params)
 	if err != nil {
 		return err
 	}
diff --git a/contrib/codecs/rdwr/codec.go b/contrib/codecs/rdwr/codec.go
index 752f64caed5469e8db30846019aaf2672b634a16..9235b1252d899e744357c3813880d3d5b594bcf0 100644
--- a/contrib/codecs/rdwr/codec.go
+++ b/contrib/codecs/rdwr/codec.go
@@ -8,7 +8,7 @@ import (
 
 	"github.com/goccy/go-json"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/serverutil"
 )
 
@@ -37,11 +37,11 @@ func NewCodec(rd io.Reader, wr io.Writer) *Codec {
 }
 
 // gets the peer info
-func (c *Codec) PeerInfo() codec.PeerInfo {
-	return codec.PeerInfo{
+func (c *Codec) PeerInfo() jsonrpc.PeerInfo {
+	return jsonrpc.PeerInfo{
 		Transport:  "ipc",
 		RemoteAddr: "",
-		HTTP:       codec.HttpInfo{},
+		HTTP:       jsonrpc.HttpInfo{},
 	}
 }
 
@@ -57,7 +57,7 @@ func (c *Codec) decodeSingleMessage(ctx context.Context) (*serverutil.Bundle, er
 	return serverutil.ParseBundle(c.decBuf), nil
 }
 
-func (c *Codec) ReadBatch(ctx context.Context) ([]*codec.Message, bool, error) {
+func (c *Codec) ReadBatch(ctx context.Context) ([]*jsonrpc.Message, bool, error) {
 	ans, err := c.decodeSingleMessage(ctx)
 	if err != nil {
 		return nil, false, err
diff --git a/contrib/codecs/rdwr/testing.go b/contrib/codecs/rdwr/testing.go
index 7edb73d655391768481337f3b4966e144285bcd7..60e9da19bdd6b567c3c07285650e054b80782658 100644
--- a/contrib/codecs/rdwr/testing.go
+++ b/contrib/codecs/rdwr/testing.go
@@ -4,8 +4,8 @@ import (
 	"context"
 	"io"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -17,7 +17,7 @@ func ServerMaker() (*server.Server, jrpctest.ClientMaker, func()) {
 	go func() {
 		s.ServeCodec(context.Background(), clientCodec)
 	}()
-	return s, func() codec.Conn {
+	return s, func() jsonrpc.Conn {
 		return NewClient(rd_s, wr_c)
 	}, func() {}
 }
diff --git a/contrib/codecs/registry.go b/contrib/codecs/registry.go
index 122cdc593cb9768ddf94f67d0a7fc016739da318..954c0a7d4906d11c32d33bcafdaa21af3a4e3430 100644
--- a/contrib/codecs/registry.go
+++ b/contrib/codecs/registry.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"net/url"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -18,7 +18,7 @@ func RegisterHandler(fn handlerFunc, names ...string) {
 	}
 }
 
-type dialerFunc = func(ctx context.Context, url string) (codec.Conn, error)
+type dialerFunc = func(ctx context.Context, url string) (jsonrpc.Conn, error)
 
 var dialers map[string]dialerFunc = map[string]dialerFunc{}
 
diff --git a/contrib/codecs/websocket/client.go b/contrib/codecs/websocket/client.go
index d71234529d27bec0a815d92f9779b777efb099b9..24f47d16bd3eb9de4a7aa291e266532cf8a08a0c 100644
--- a/contrib/codecs/websocket/client.go
+++ b/contrib/codecs/websocket/client.go
@@ -2,7 +2,7 @@ package websocket
 
 import (
 	"gfx.cafe/open/jrpc/contrib/codecs/rdwr"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 
 	"context"
 
@@ -21,7 +21,7 @@ func newClient(conn *websocket.Conn) (*Client, error) {
 		Client: rdwr.NewClient(netConn, netConn),
 		conn:   conn,
 	}
-	c.SetHandlerPeer(codec.PeerInfo{
+	c.SetHandlerPeer(jsonrpc.PeerInfo{
 		Transport:  "ws",
 		RemoteAddr: "",
 	})
diff --git a/contrib/codecs/websocket/codec.go b/contrib/codecs/websocket/codec.go
index 43f1cdabc3bc84b47b25ba29078cd583e71b7142..35fc49472f8a22fd4a9692ba49d6da67e457afe2 100644
--- a/contrib/codecs/websocket/codec.go
+++ b/contrib/codecs/websocket/codec.go
@@ -12,7 +12,7 @@ import (
 
 	_ "net/http/pprof"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/serverutil"
 )
 
@@ -26,7 +26,7 @@ type Codec struct {
 	decBuf  json.RawMessage
 	decLock sync.Mutex
 
-	i codec.PeerInfo
+	i jsonrpc.PeerInfo
 }
 
 func newWebsocketCodec(ctx context.Context, conn *websocket.Conn, host string, req http.Header) *Codec {
@@ -88,7 +88,7 @@ func (c *Codec) decodeSingleMessage(ctx context.Context) (*serverutil.Bundle, er
 	return serverutil.ParseBundle(c.decBuf), nil
 }
 
-func (c *Codec) ReadBatch(ctx context.Context) ([]*codec.Message, bool, error) {
+func (c *Codec) ReadBatch(ctx context.Context) ([]*jsonrpc.Message, bool, error) {
 	ans, err := c.decodeSingleMessage(ctx)
 	if err != nil {
 		return nil, false, err
@@ -127,7 +127,7 @@ func (c *Codec) Flush() error {
 	return nil
 }
 
-func (c *Codec) PeerInfo() codec.PeerInfo {
+func (c *Codec) PeerInfo() jsonrpc.PeerInfo {
 	return c.i
 }
 
@@ -149,4 +149,4 @@ func (c *Codec) RemoteAddr() string {
 	return c.i.RemoteAddr
 }
 
-var _ codec.ReaderWriter = (*Codec)(nil)
+var _ jsonrpc.ReaderWriter = (*Codec)(nil)
diff --git a/contrib/codecs/websocket/testing.go b/contrib/codecs/websocket/testing.go
index e5bdb46c0156c8c5433ab035fa1126e64e1ee3d8..ffef9c70988f70f05d9437534f06e4327c571b2c 100644
--- a/contrib/codecs/websocket/testing.go
+++ b/contrib/codecs/websocket/testing.go
@@ -4,15 +4,15 @@ import (
 	"context"
 	"net/http/httptest"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
 func ServerMaker() (*server.Server, jrpctest.ClientMaker, func()) {
 	s := jrpctest.NewServer()
 	hsrv := httptest.NewServer(&Server{Server: s})
-	return s, func() codec.Conn {
+	return s, func() jsonrpc.Conn {
 		conn, err := DialWebsocket(context.Background(), hsrv.URL, "")
 		if err != nil {
 			panic(err)
diff --git a/contrib/codecs/websocket/websocket_test.go b/contrib/codecs/websocket/websocket_test.go
index 45171534e4ba07eee6abae0cd62b11d3165cb7cd..cd68fa8c4fb72f2e052eca4ceb573abc3a89aada 100644
--- a/contrib/codecs/websocket/websocket_test.go
+++ b/contrib/codecs/websocket/websocket_test.go
@@ -8,8 +8,8 @@ import (
 
 	"gfx.cafe/open/jrpc/contrib/codecs/websocket"
 	"gfx.cafe/open/jrpc/contrib/jmux"
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"gfx.cafe/open/jrpc/pkg/jrpctest"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -110,7 +110,7 @@ func TestWebsocketPeerInfo(t *testing.T) {
 	}
 
 	// Request peer information.
-	var connInfo codec.PeerInfo
+	var connInfo jsonrpc.PeerInfo
 	if err := c.Do(nil, &connInfo, "test_peerInfo", []any{}); err != nil {
 		t.Fatal(err)
 	}
diff --git a/contrib/extension/subscription/client.go b/contrib/extension/subscription/client.go
index fa89a1a73bc9c84295239b5ffa1784b8407689f7..86a34c90b3e0536870fc621c4e4910ac9cbfadb6 100644
--- a/contrib/extension/subscription/client.go
+++ b/contrib/extension/subscription/client.go
@@ -8,15 +8,15 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
-var _ codec.StreamingConn = (*WrapClient)(nil)
+var _ jsonrpc.StreamingConn = (*WrapClient)(nil)
 
 type WrapClient struct {
 	subs map[string]*clientSub
 
-	conn codec.StreamingConn
+	conn jsonrpc.StreamingConn
 	mu   sync.RWMutex
 }
 
@@ -24,15 +24,15 @@ func (w *WrapClient) Closed() <-chan struct{} {
 	return w.conn.Closed()
 }
 
-func NewWrapClient(conn codec.StreamingConn) *WrapClient {
+func NewWrapClient(conn jsonrpc.StreamingConn) *WrapClient {
 	return &WrapClient{
 		subs: map[string]*clientSub{},
 		conn: conn,
 	}
 }
 
-func (c *WrapClient) Middleware(h codec.Handler) codec.Handler {
-	return codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+func (c *WrapClient) Middleware(h jsonrpc.Handler) jsonrpc.Handler {
+	return jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		// use normal handler
 		if !strings.HasSuffix(r.Method, notificationMethodSuffix) {
 			h.ServeRPC(w, r)
@@ -127,7 +127,7 @@ func (c *WrapClient) Do(ctx context.Context, result any, method string, params a
 	return c.conn.Do(ctx, result, method, params)
 }
 
-func (c *WrapClient) BatchCall(ctx context.Context, b ...*codec.BatchElem) error {
+func (c *WrapClient) BatchCall(ctx context.Context, b ...*jsonrpc.BatchElem) error {
 	return c.conn.BatchCall(ctx, b...)
 }
 
@@ -135,7 +135,7 @@ func (c *WrapClient) Close() error {
 	return c.conn.Close()
 }
 
-func (c *WrapClient) Mount(m codec.Middleware) {
+func (c *WrapClient) Mount(m jsonrpc.Middleware) {
 	c.conn.Mount(m)
 }
 
@@ -147,7 +147,7 @@ func (c *WrapClient) Notify(ctx context.Context, method string, params any) erro
 
 type clientSub struct {
 	engine    *WrapClient
-	conn      codec.StreamingConn
+	conn      jsonrpc.StreamingConn
 	namespace string
 	id        string
 	channel   reflect.Value
diff --git a/contrib/extension/subscription/conn.go b/contrib/extension/subscription/conn.go
index fa4b89859a48022f28cbfd27ee01976a53652487..acece572af77fce9a4565559e20a7f8b26733cc8 100644
--- a/contrib/extension/subscription/conn.go
+++ b/contrib/extension/subscription/conn.go
@@ -3,20 +3,20 @@ package subscription
 import (
 	"context"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type Conn interface {
 	Subscribe(ctx context.Context, namespace string, channel any, args any) (ClientSubscription, error)
 
-	codec.StreamingConn
+	jsonrpc.StreamingConn
 }
 
-func UpgradeConn(c codec.Conn, err error) (Conn, error) {
+func UpgradeConn(c jsonrpc.Conn, err error) (Conn, error) {
 	if err != nil {
 		return nil, err
 	}
-	if val, ok := c.(codec.StreamingConn); ok {
+	if val, ok := c.(jsonrpc.StreamingConn); ok {
 		engine := NewWrapClient(val)
 		val.Mount(engine.Middleware)
 		return engine, nil
diff --git a/contrib/extension/subscription/engine.go b/contrib/extension/subscription/engine.go
index 50342b6e4191807845182cff067dc19eba6e2876..184e06175d231f31fa0e03950d9827a43936af02 100644
--- a/contrib/extension/subscription/engine.go
+++ b/contrib/extension/subscription/engine.go
@@ -5,7 +5,7 @@ import (
 	"strings"
 	"sync"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type Engine struct {
@@ -36,9 +36,9 @@ func (e *Engine) closeSub(subid SubID) (bool, error) {
 	return ok, nil
 }
 
-func (e *Engine) Middleware() func(codec.Handler) codec.Handler {
-	return func(h codec.Handler) codec.Handler {
-		return codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+func (e *Engine) Middleware() func(jsonrpc.Handler) jsonrpc.Handler {
+	return func(h jsonrpc.Handler) jsonrpc.Handler {
+		return jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 			// its a subscription, so install a notification handler
 			switch {
 			case strings.HasSuffix(r.Method, serviceMethodSeparator+subscribeMethodSuffix):
diff --git a/contrib/extension/subscription/subscription.go b/contrib/extension/subscription/subscription.go
index 85a9d3ac060a0c568433522e53346db32ea9bcd7..91d53d9c77937412e2368de0599638eb52b3d40e 100644
--- a/contrib/extension/subscription/subscription.go
+++ b/contrib/extension/subscription/subscription.go
@@ -9,7 +9,7 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/util/go/frand"
 
 	json "github.com/goccy/go-json"
@@ -83,7 +83,7 @@ func NotifierFromContext(ctx context.Context) (*Notifier, bool) {
 // Notifier is tied to a RPC connection that supports subscriptions.
 // Server callbacks use the notifier to send notifications.
 type Notifier struct {
-	h         codec.ResponseWriter
+	h         jsonrpc.ResponseWriter
 	namespace string
 
 	mu sync.Mutex
diff --git a/contrib/handlers/argreflect/json.go b/contrib/handlers/argreflect/json.go
index 48fe288681a60737288cbf52657237c778107e8e..b66015518138268615cb0c3a0e5fa2b049291f70 100644
--- a/contrib/handlers/argreflect/json.go
+++ b/contrib/handlers/argreflect/json.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"reflect"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"github.com/go-faster/jx"
 	"github.com/goccy/go-json"
 )
@@ -25,12 +25,12 @@ func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]
 	case string(rawArgs) == "null":
 		return nil, nil
 	default:
-		return nil, codec.NewInvalidParamsError("non-array args")
+		return nil, jsonrpc.NewInvalidParamsError("non-array args")
 	}
 	// Set any missing args to nil.
 	for i := len(args); i < len(types); i++ {
 		if types[i].Kind() != reflect.Ptr {
-			return nil, codec.NewInvalidParamsError(fmt.Sprintf("missing value for required argument %d", i))
+			return nil, jsonrpc.NewInvalidParamsError(fmt.Sprintf("missing value for required argument %d", i))
 		}
 		args = append(args, reflect.Zero(types[i]))
 	}
@@ -44,27 +44,27 @@ func parseArgumentArray(p json.RawMessage, types []reflect.Type) ([]reflect.Valu
 	args := make([]reflect.Value, 0, len(types))
 	iter, err := dec.ArrIter()
 	if err != nil {
-		return args, codec.NewInvalidParamsError("expected array")
+		return args, jsonrpc.NewInvalidParamsError("expected array")
 	}
 	i := 0
 	for iter.Next() {
 		if err := iter.Err(); err != nil {
-			return args, codec.NewInvalidParamsError(fmt.Sprintf("iterator err %d: %v", i, err))
+			return args, jsonrpc.NewInvalidParamsError(fmt.Sprintf("iterator err %d: %v", i, err))
 		}
 		if i >= len(types) {
-			return args, codec.NewInvalidParamsError(fmt.Sprintf("too many arguments, want at most %d", len(types)))
+			return args, jsonrpc.NewInvalidParamsError(fmt.Sprintf("too many arguments, want at most %d", len(types)))
 		}
 		argval := reflect.New(types[i])
 		raw, err := dec.Raw()
 		if err != nil {
-			return args, codec.NewInvalidParamsError(fmt.Sprintf("invalid raw argument %d: %v", i, err))
+			return args, jsonrpc.NewInvalidParamsError(fmt.Sprintf("invalid raw argument %d: %v", i, err))
 		}
 		err = json.Unmarshal(raw, argval.Interface())
 		if err != nil {
-			return args, codec.NewInvalidParamsError(fmt.Sprintf("invalid argument %d: %v", i, err))
+			return args, jsonrpc.NewInvalidParamsError(fmt.Sprintf("invalid argument %d: %v", i, err))
 		}
 		if argval.IsNil() && types[i].Kind() != reflect.Ptr {
-			return nil, codec.NewInvalidParamsError(fmt.Sprintf("missing value for required argument %d", i))
+			return nil, jsonrpc.NewInvalidParamsError(fmt.Sprintf("missing value for required argument %d", i))
 		}
 		args = append(args, argval.Elem())
 		i++
diff --git a/contrib/handlers/argreflect/reflect_handler.go b/contrib/handlers/argreflect/reflect_handler.go
index cec861649bf56d2d3c4bbd8a545992aa7fd0a37f..242263fa8ad4b4c5dd066b7e85457eb9dbd79f27 100644
--- a/contrib/handlers/argreflect/reflect_handler.go
+++ b/contrib/handlers/argreflect/reflect_handler.go
@@ -7,7 +7,7 @@ import (
 	"runtime"
 	"unicode"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 var (
@@ -15,16 +15,16 @@ var (
 	errorType   = reflect.TypeOf((*error)(nil)).Elem()
 )
 
-func SuitableCallbacks(receiver reflect.Value) map[string]codec.Handler {
+func SuitableCallbacks(receiver reflect.Value) map[string]jsonrpc.Handler {
 	return suitableCallbacks(receiver)
 }
 
 // suitableCallbacks iterates over the methods of the given type. It determines if a method
 // satisfies the criteria for a RPC callback or a subscription callback and adds it to the
 // collection of callbacks. See server documentation for a summary of these criteria.
-func suitableCallbacks(receiver reflect.Value) map[string]codec.Handler {
+func suitableCallbacks(receiver reflect.Value) map[string]jsonrpc.Handler {
 	typ := receiver.Type()
-	callbacks := make(map[string]codec.Handler)
+	callbacks := make(map[string]jsonrpc.Handler)
 	for m := 0; m < typ.NumMethod(); m++ {
 		method := typ.Method(m)
 		if method.PkgPath != "" {
@@ -50,11 +50,11 @@ type callback struct {
 }
 
 // callback handler implements handler for the original receiver style that geth used
-func (e *callback) ServeRPC(w codec.ResponseWriter, r *codec.Request) {
+func (e *callback) ServeRPC(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 	argTypes := append([]reflect.Type{}, e.argTypes...)
 	args, err := parsePositionalArguments(r.Params, argTypes)
 	if err != nil {
-		w.Send(nil, codec.NewInvalidParamsError(err.Error()))
+		w.Send(nil, jsonrpc.NewInvalidParamsError(err.Error()))
 		return
 	}
 	// Create the argument slice.
@@ -87,13 +87,13 @@ func (e *callback) ServeRPC(w codec.ResponseWriter, r *codec.Request) {
 		return
 	}
 	if len(results) == 0 {
-		w.Send(codec.Null, nil)
+		w.Send(jsonrpc.Null, nil)
 		return
 	}
 	w.Send(results[0].Interface(), nil)
 }
 
-func NewCallback(receiver, fn reflect.Value) codec.Handler {
+func NewCallback(receiver, fn reflect.Value) jsonrpc.Handler {
 	return newCallback(receiver, fn)
 }
 
diff --git a/contrib/jmux/mux.go b/contrib/jmux/mux.go
index 4102684f09b018efb0ed3208c0100a1fd13e388e..1264a8475634c63fa95566f567e313792955622c 100644
--- a/contrib/jmux/mux.go
+++ b/contrib/jmux/mux.go
@@ -9,7 +9,7 @@ import (
 	"sync"
 
 	"gfx.cafe/open/jrpc/contrib/handlers/argreflect"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 var _ Router = &Mux{}
@@ -28,13 +28,13 @@ const sepString = string(sepRune)
 type Mux struct {
 	// The computed mux handler made of the chained middleware stack and
 	// the tree router
-	handler codec.Handler
+	handler jsonrpc.Handler
 
 	// The radix trie router
 	tree *node
 
 	// Custom method not allowed handler
-	methodNotAllowedHandler codec.HandlerFunc
+	methodNotAllowedHandler jsonrpc.HandlerFunc
 
 	// A reference to the parent mux used by subrouters when mounting
 	// to a parent mux
@@ -44,10 +44,10 @@ type Mux struct {
 	pool *sync.Pool
 
 	// Custom route not found handler
-	notFoundHandler codec.HandlerFunc
+	notFoundHandler jsonrpc.HandlerFunc
 
 	// The middleware stack
-	middlewares []func(codec.Handler) codec.Handler
+	middlewares []func(jsonrpc.Handler) jsonrpc.Handler
 
 	// Controls the behaviour of middleware chain generation when a mux
 	// is registered as an inline group inside another mux.
@@ -93,7 +93,7 @@ func (m *Mux) RegisterFunc(name string, rcvr any) error {
 // ServeRPC is the single method of the Handler interface that makes
 // Mux interoperable with the standard library. It uses a sync.Pool to get and
 // reuse routing contexts for each request.
-func (mx *Mux) ServeRPC(w codec.ResponseWriter, r *codec.Request) {
+func (mx *Mux) ServeRPC(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 	// Ensure the mux has some routes defined on the mux
 	if mx.handler == nil {
 		mx.NotFoundHandler().ServeRPC(w, r)
@@ -130,7 +130,7 @@ func (mx *Mux) ServeRPC(w codec.ResponseWriter, r *codec.Request) {
 // route to a specific handler, which provides opportunity to respond early,
 // change the course of the request execution, or set request-scoped values for
 // the next Handler.
-func (mx *Mux) Use(middlewares ...func(codec.Handler) codec.Handler) {
+func (mx *Mux) Use(middlewares ...func(jsonrpc.Handler) jsonrpc.Handler) {
 	if mx.handler != nil {
 		panic("chi: all middlewares must be defined before routes on a mux")
 	}
@@ -139,19 +139,19 @@ func (mx *Mux) Use(middlewares ...func(codec.Handler) codec.Handler) {
 
 // Handle adds the route `pattern` that matches any jrpc method to
 // execute the `handler` Handler.
-func (mx *Mux) Handle(pattern string, handler codec.Handler) {
+func (mx *Mux) Handle(pattern string, handler jsonrpc.Handler) {
 	mx.handle(pattern, handler)
 }
 
 // HandleFunc adds the route `pattern` that matches any jrpc method to
 // execute the `handlerFn` HandlerFunc.
-func (mx *Mux) HandleFunc(pattern string, handlerFn codec.HandlerFunc) {
+func (mx *Mux) HandleFunc(pattern string, handlerFn jsonrpc.HandlerFunc) {
 	mx.handle(pattern, handlerFn)
 }
 
 // NotFound sets a custom HandlerFunc for routing paths that could
 // not be found. The default 404 handler is `NotFound`.
-func (mx *Mux) NotFound(handlerFn codec.HandlerFunc) {
+func (mx *Mux) NotFound(handlerFn jsonrpc.HandlerFunc) {
 	// Build NotFound handler chain
 	m := mx
 	hFn := handlerFn
@@ -171,7 +171,7 @@ func (mx *Mux) NotFound(handlerFn codec.HandlerFunc) {
 
 // MethodNotAllowed sets a custom HandlerFunc for routing paths where the
 // method is unresolved. The default handler returns a 405 with an empty body.
-func (mx *Mux) MethodNotAllowed(handlerFn codec.HandlerFunc) {
+func (mx *Mux) MethodNotAllowed(handlerFn jsonrpc.HandlerFunc) {
 	// Build MethodNotAllowed handler chain
 	m := mx
 	hFn := handlerFn
@@ -190,7 +190,7 @@ func (mx *Mux) MethodNotAllowed(handlerFn codec.HandlerFunc) {
 }
 
 // With adds inline middlewares for an endpoint handler.
-func (mx *Mux) With(middlewares ...func(codec.Handler) codec.Handler) Router {
+func (mx *Mux) With(middlewares ...func(jsonrpc.Handler) jsonrpc.Handler) Router {
 	// Similarly as in handle(), we must build the mux handler once additional
 	// middleware registration isn't allowed for this stack, like now.
 	if !mx.inline && mx.handler == nil {
@@ -243,7 +243,7 @@ func (mx *Mux) Route(pattern string, fn func(r Router)) Router {
 // Note that Mount() simply sets a wildcard along the `pattern` that will continue
 // routing at the `handler`, which in most cases is another chi.Router. As a result,
 // if you define two Mount() routes on the exact same pattern the mount will panic.
-func (mx *Mux) Mount(pattern string, handler codec.Handler) {
+func (mx *Mux) Mount(pattern string, handler jsonrpc.Handler) {
 	if handler == nil {
 		panic(fmt.Sprintf("chi: attempting to Mount() a nil handler on '%s'", pattern))
 	}
@@ -263,7 +263,7 @@ func (mx *Mux) Mount(pattern string, handler codec.Handler) {
 		subr.MethodNotAllowed(mx.methodNotAllowedHandler)
 	}
 
-	mountHandler := codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+	mountHandler := jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		rctx := RouteContext(r.Context())
 
 		// shift the url path past the previous subrouter
@@ -319,7 +319,7 @@ func (mx *Mux) Match(rctx *Context, path string) bool {
 
 // NotFoundHandler returns the default Mux 404 responder whenever a route
 // cannot be found.
-func (mx *Mux) NotFoundHandler() codec.HandlerFunc {
+func (mx *Mux) NotFoundHandler() jsonrpc.HandlerFunc {
 	if mx.notFoundHandler != nil {
 		return mx.notFoundHandler
 	}
@@ -328,7 +328,7 @@ func (mx *Mux) NotFoundHandler() codec.HandlerFunc {
 
 // MethodNotAllowedHandler returns the default Mux 405 responder whenever
 // a method cannot be resolved for a route.
-func (mx *Mux) MethodNotAllowedHandler() codec.HandlerFunc {
+func (mx *Mux) MethodNotAllowedHandler() jsonrpc.HandlerFunc {
 	if mx.methodNotAllowedHandler != nil {
 		return mx.methodNotAllowedHandler
 	}
@@ -337,7 +337,7 @@ func (mx *Mux) MethodNotAllowedHandler() codec.HandlerFunc {
 
 // handle registers a Handler in the routing tree for a particular jrpc method
 // and routing pattern.
-func (mx *Mux) handle(pattern string, handler codec.Handler) *node {
+func (mx *Mux) handle(pattern string, handler jsonrpc.Handler) *node {
 	if len(pattern) == 0 {
 		panic(fmt.Sprintf("rpc: routing pattern must not be empty in '%s'", pattern))
 	}
@@ -352,9 +352,9 @@ func (mx *Mux) handle(pattern string, handler codec.Handler) *node {
 	}
 
 	// Build endpoint handler with inline middlewares for the route
-	var h codec.Handler
+	var h jsonrpc.Handler
 	if mx.inline {
-		mx.handler = codec.HandlerFunc(mx.routeRPC)
+		mx.handler = jsonrpc.HandlerFunc(mx.routeRPC)
 		h = Chain(mx.middlewares...).Handler(handler)
 	} else {
 		h = handler
@@ -366,7 +366,7 @@ func (mx *Mux) handle(pattern string, handler codec.Handler) *node {
 
 // routeRPC routes a Request through the Mux routing tree to serve
 // the matching handler for a particular jrpc method.
-func (mx *Mux) routeRPC(w codec.ResponseWriter, r *codec.Request) {
+func (mx *Mux) routeRPC(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 	// Grab the route context object
 	rctx := r.Context().Value(RouteCtxKey).(*Context)
 
@@ -418,15 +418,15 @@ func (mx *Mux) updateSubRoutes(fn func(subMux *Mux)) {
 // point, no other middlewares can be registered on this Mux's stack. But you can still
 // compose additional middlewares via Group()'s or using a chained middleware handler.
 func (mx *Mux) updateRouteHandler() {
-	mx.handler = codec.ChainMiddlewares(mx.middlewares, codec.HandlerFunc(mx.routeRPC))
+	mx.handler = jsonrpc.ChainMiddlewares(mx.middlewares, jsonrpc.HandlerFunc(mx.routeRPC))
 }
 
 // methodNotAllowedHandler is a helper function to respond with a 405,
 // method not allowed.
-func methodNotAllowedHandler(w codec.ResponseWriter, r *codec.Request) {
+func methodNotAllowedHandler(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 	w.Send(nil, errors.New("forbidden"))
 }
 
-func NotFound(w codec.ResponseWriter, r *codec.Request) {
-	w.Send(nil, codec.NewMethodNotFoundError(r.Method))
+func NotFound(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
+	w.Send(nil, jsonrpc.NewMethodNotFoundError(r.Method))
 }
diff --git a/contrib/jmux/router.go b/contrib/jmux/router.go
index 05c81817f98abfe21c2245a183cc829d9b0309c8..b15a7bbc1819a29b9264cfdb4c839abb7baacbe2 100644
--- a/contrib/jmux/router.go
+++ b/contrib/jmux/router.go
@@ -1,7 +1,7 @@
 package jmux
 
 import (
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 // NewRouter returns a new Mux object that implements the Router interface.
@@ -21,15 +21,15 @@ type StructReflector interface {
 // Router consisting of the core routing methods used by chi's Mux,
 // adapted to fit json-rpc.
 type Router interface {
-	codec.Handler
+	jsonrpc.Handler
 	Routes
 	StructReflector
 
 	// Use appends one or more middlewares onto the Router stack.
-	Use(middlewares ...func(codec.Handler) codec.Handler)
+	Use(middlewares ...func(jsonrpc.Handler) jsonrpc.Handler)
 
 	// With adds inline middlewares for an endpoint handler.
-	With(middlewares ...func(codec.Handler) codec.Handler) Router
+	With(middlewares ...func(jsonrpc.Handler) jsonrpc.Handler) Router
 
 	// Group adds a new inline-Router along the current routing
 	// path, with a fresh middleware stack for the inline-Router.
@@ -39,16 +39,16 @@ type Router interface {
 	Route(pattern string, fn func(r Router)) Router
 
 	// Mount attaches another Handler along ./pattern/*
-	Mount(pattern string, h codec.Handler)
+	Mount(pattern string, h jsonrpc.Handler)
 
 	// Handle and HandleFunc adds routes for `pattern` that matches
 	// all HTTP methods.
-	Handle(pattern string, h codec.Handler)
-	HandleFunc(pattern string, h codec.HandlerFunc)
+	Handle(pattern string, h jsonrpc.Handler)
+	HandleFunc(pattern string, h jsonrpc.HandlerFunc)
 
 	// NotFound defines a handler to respond whenever a route could
 	// not be found.
-	NotFound(h codec.HandlerFunc)
+	NotFound(h jsonrpc.HandlerFunc)
 }
 
 // Routes interface adds two methods for router traversal, which is also
@@ -68,4 +68,4 @@ type Routes interface {
 
 // Middlewares type is a slice of standard middleware handlers with methods
 // to compose middleware chains and Handler's.
-type Middlewares = codec.Middlewares
+type Middlewares = jsonrpc.Middlewares
diff --git a/contrib/jmux/router_chain.go b/contrib/jmux/router_chain.go
index 125fe197bb135d0965e3125e1cd8bdc43cf7a980..9776cacf98661c848a5035110baed19e9a16f12c 100644
--- a/contrib/jmux/router_chain.go
+++ b/contrib/jmux/router_chain.go
@@ -1,12 +1,12 @@
 package jmux
 
 import (
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 // ChainHandler is a Handler with support for handler composition and
 // execution.
-type ChainHandler = codec.ChainHandler
+type ChainHandler = jsonrpc.ChainHandler
 
 // Chain returns a Middlewares type from a slice of middleware handlers.
-var Chain = codec.Chain
+var Chain = jsonrpc.Chain
diff --git a/contrib/jmux/router_context.go b/contrib/jmux/router_context.go
index c55247f2bff93f43d977a0533e72cf4a171883e5..f27ccbdc3994bb80dfb2881154b96f24e4fd7cf3 100644
--- a/contrib/jmux/router_context.go
+++ b/contrib/jmux/router_context.go
@@ -4,11 +4,11 @@ import (
 	"context"
 	"strings"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 // MethodParam returns the url parameter from a Request object.
-func MethodParam(r *codec.Request, key string) string {
+func MethodParam(r *jsonrpc.Request, key string) string {
 	if rctx := RouteContext(r.Context()); rctx != nil {
 		return rctx.MethodParam(key)
 	}
diff --git a/contrib/jmux/router_tree.go b/contrib/jmux/router_tree.go
index 4e4a44f82822d09e45bf195c2eaa5af6eb8b2f8b..c4233069d683ea029dada1c3ab791b4c523c436f 100644
--- a/contrib/jmux/router_tree.go
+++ b/contrib/jmux/router_tree.go
@@ -9,7 +9,7 @@ import (
 	"sort"
 	"strings"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type nodeTyp uint8
@@ -50,7 +50,7 @@ type node struct {
 
 type endpoint struct {
 	// endpoint handler
-	handler codec.Handler
+	handler jsonrpc.Handler
 
 	// pattern is the routing pattern for handler nodes
 	pattern string
@@ -59,7 +59,7 @@ type endpoint struct {
 	paramKeys []string
 }
 
-func (n *node) InsertRoute(pattern string, handler codec.Handler) *node {
+func (n *node) InsertRoute(pattern string, handler jsonrpc.Handler) *node {
 	var parent *node
 	search := pattern
 	for {
@@ -263,7 +263,7 @@ func (n *node) getEdge(ntyp nodeTyp, label, tail byte, prefix string) *node {
 	return nil
 }
 
-func (n *node) setEndpoint(handler codec.Handler, pattern string) {
+func (n *node) setEndpoint(handler jsonrpc.Handler, pattern string) {
 	paramKeys := patParamKeys(pattern)
 	n.endpoint = &endpoint{
 		handler:   handler,
@@ -272,7 +272,7 @@ func (n *node) setEndpoint(handler codec.Handler, pattern string) {
 	}
 }
 
-func (n *node) FindRoute(rctx *Context, path string) (*node, *endpoint, codec.Handler) {
+func (n *node) FindRoute(rctx *Context, path string) (*node, *endpoint, jsonrpc.Handler) {
 	// Reset the context routing pattern and params
 	rctx.routePattern = ""
 	rctx.routeParams.Keys = rctx.routeParams.Keys[:0]
@@ -689,21 +689,21 @@ func (ns nodes) findEdge(label byte) *node {
 // Route describes the details of a routing handler.
 type Route struct {
 	SubRoutes Routes
-	Handler   codec.Handler
+	Handler   jsonrpc.Handler
 	Pattern   string
 }
 
 // WalkFunc is the type of the function called for each method and route visited by Walk.
-type WalkFunc func(route string, handler codec.Handler, middlewares ...func(codec.Handler) codec.Handler) error
+type WalkFunc func(route string, handler jsonrpc.Handler, middlewares ...func(jsonrpc.Handler) jsonrpc.Handler) error
 
 // Walk walks any router tree that implements Routes interface.
 func Walk(r Routes, walkFn WalkFunc) error {
 	return walk(r, walkFn, "")
 }
 
-func walk(r Routes, walkFn WalkFunc, parentRoute string, parentMw ...func(codec.Handler) codec.Handler) error {
+func walk(r Routes, walkFn WalkFunc, parentRoute string, parentMw ...func(jsonrpc.Handler) jsonrpc.Handler) error {
 	for _, route := range r.Routes() {
-		mws := make([]func(codec.Handler) codec.Handler, len(parentMw))
+		mws := make([]func(jsonrpc.Handler) jsonrpc.Handler, len(parentMw))
 		copy(mws, parentMw)
 		mws = append(mws, r.Middlewares()...)
 
diff --git a/contrib/middleware/log.go b/contrib/middleware/log.go
index a14e2655d67173fc32587ac9706f09012146309e..4e4329d58724d874590bce464bac015800c70152 100644
--- a/contrib/middleware/log.go
+++ b/contrib/middleware/log.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"time"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 
 	"log/slog"
 )
@@ -15,9 +15,9 @@ type ctxKeyLogger int
 // RequestIDKey is the key that holds the unique request ID in a request context.
 const LoggerKey ctxKeyLogger = 76
 
-func NewLogger(logger *slog.Logger) func(next codec.Handler) codec.Handler {
-	return func(next codec.Handler) codec.Handler {
-		fn := func(w codec.ResponseWriter, r *codec.Request) {
+func NewLogger(logger *slog.Logger) func(next jsonrpc.Handler) jsonrpc.Handler {
+	return func(next jsonrpc.Handler) jsonrpc.Handler {
+		fn := func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 			start := time.Now()
 			lg := logger.With(
 				"remote", r.Remote(),
@@ -35,11 +35,11 @@ func NewLogger(logger *slog.Logger) func(next codec.Handler) codec.Handler {
 			)
 			logger.LogAttrs(r.Context(), slog.LevelDebug, "RPC Request")
 		}
-		return codec.HandlerFunc(fn)
+		return jsonrpc.HandlerFunc(fn)
 	}
 }
 
-func Logger(next codec.Handler) codec.Handler {
+func Logger(next jsonrpc.Handler) jsonrpc.Handler {
 	lh := slog.Default()
 	return NewLogger(lh)(next)
 }
diff --git a/contrib/middleware/middleware.go b/contrib/middleware/middleware.go
index 491a05a5d9c46b680d3615c2bab0d24b265a7ee5..0a87c84f3d80047e6d0a0703a5dcc1a6ddf577b4 100644
--- a/contrib/middleware/middleware.go
+++ b/contrib/middleware/middleware.go
@@ -1,13 +1,13 @@
 package middleware
 
 import (
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 // New will create a new middleware handler from a jrpc.Handler.
-func New(h codec.Handler) func(next codec.Handler) codec.Handler {
-	return func(next codec.Handler) codec.Handler {
-		return codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+func New(h jsonrpc.Handler) func(next jsonrpc.Handler) jsonrpc.Handler {
+	return func(next jsonrpc.Handler) jsonrpc.Handler {
+		return jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 			h.ServeRPC(w, r)
 		})
 	}
diff --git a/contrib/middleware/recoverer.go b/contrib/middleware/recoverer.go
index 410224759678c920e2fd75c6546ae86ec1609f69..33000ea375442726828c96cc2a45e207907cd0ae 100644
--- a/contrib/middleware/recoverer.go
+++ b/contrib/middleware/recoverer.go
@@ -7,7 +7,7 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"io"
 	"os"
 	"runtime/debug"
@@ -19,8 +19,8 @@ import (
 // possible. Recoverer prints a request ID if one is provided.
 //
 // Alternatively, look at jrpcs://github.com/go-chi/jrpclog middleware pkgs.
-func Recoverer(next codec.Handler) codec.Handler {
-	fn := func(w codec.ResponseWriter, r *codec.Request) {
+func Recoverer(next jsonrpc.Handler) jsonrpc.Handler {
+	fn := func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		defer func() {
 			if rvr := recover(); rvr != nil {
 				PrintPrettyStack(rvr)
@@ -31,7 +31,7 @@ func Recoverer(next codec.Handler) codec.Handler {
 		next.ServeRPC(w, r)
 	}
 
-	return codec.HandlerFunc(fn)
+	return jsonrpc.HandlerFunc(fn)
 }
 
 // for ability to test the PrintPrettyStack function
diff --git a/contrib/middleware/replacer.go b/contrib/middleware/replacer.go
index e77065baacea5784be5214c236074b44e413f905..749624bd5f79e5af6e8d511a168279246208d5e2 100644
--- a/contrib/middleware/replacer.go
+++ b/contrib/middleware/replacer.go
@@ -3,15 +3,15 @@ package middleware
 import (
 	"strings"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 var LegacyUnderscoreReplacer = MethodReplacer(strings.NewReplacer("_", "/"))
 
 // MethodReplacer will use the replacer on every method before handling
-func MethodReplacer(replacer *strings.Replacer) codec.Middleware {
-	return func(next codec.Handler) codec.Handler {
-		return codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {
+func MethodReplacer(replacer *strings.Replacer) jsonrpc.Middleware {
+	return func(next jsonrpc.Handler) jsonrpc.Handler {
+		return jsonrpc.HandlerFunc(func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 			r.Method = replacer.Replace(r.Method)
 			next.ServeRPC(w, r)
 		})
diff --git a/contrib/middleware/request_id.go b/contrib/middleware/request_id.go
index cfed73f8895c43baeebca6e8e1baf3887e974f23..03d1b21b80fd8373582acc1102d095be3477dbaa 100644
--- a/contrib/middleware/request_id.go
+++ b/contrib/middleware/request_id.go
@@ -8,7 +8,7 @@ import (
 	"crypto/rand"
 	"encoding/base64"
 	"fmt"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"os"
 	"strings"
 	"sync/atomic"
@@ -66,15 +66,15 @@ func init() {
 // where "random" is a base62 random string that uniquely identifies this go
 // process, and where the last number is an atomically incremented request
 // counter.
-func RequestID(next codec.Handler) codec.Handler {
-	fn := func(w codec.ResponseWriter, r *codec.Request) {
+func RequestID(next jsonrpc.Handler) jsonrpc.Handler {
+	fn := func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		ctx := r.Context()
 		myid := atomic.AddUint64(&reqid, 1)
 		requestID := fmt.Sprintf("%s-%06d", prefix, myid)
 		ctx = context.WithValue(ctx, RequestIDKey, requestID)
 		next.ServeRPC(w, r.WithContext(ctx))
 	}
-	return codec.HandlerFunc(fn)
+	return jsonrpc.HandlerFunc(fn)
 }
 
 // GetReqID returns a request ID from the given context if one is present.
diff --git a/example/echo/main.go b/example/echo/main.go
index 54e999ffe1b12bdfb39ae1715029fd1da3fb672c..8e82aa56741f25137253587b5478f366cb20ec60 100644
--- a/example/echo/main.go
+++ b/example/echo/main.go
@@ -6,7 +6,7 @@ import (
 
 	"gfx.cafe/open/jrpc/contrib/codecs"
 	"gfx.cafe/open/jrpc/contrib/jmux"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -15,7 +15,7 @@ func main() {
 	r := jmux.NewRouter()
 	srv := server.NewServer(r)
 
-	r.HandleFunc("echo", func(w codec.ResponseWriter, r *codec.Request) {
+	r.HandleFunc("echo", func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		w.Send(r.Params, nil)
 	})
 
diff --git a/example/proxy/main.go b/example/proxy/main.go
index c13883790f41a635370b6b1211308193994f5aca..41822c1589bda7773bcfeb11018add8e788a58bd 100644
--- a/example/proxy/main.go
+++ b/example/proxy/main.go
@@ -8,7 +8,7 @@ import (
 	"gfx.cafe/open/jrpc/contrib/codecs"
 	"gfx.cafe/open/jrpc/contrib/jmux"
 	"gfx.cafe/open/jrpc/contrib/middleware"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 
 	"gfx.cafe/open/jrpc"
@@ -23,7 +23,7 @@ func main() {
 		panic(err)
 	}
 
-	r.HandleFunc("eth_*", func(w codec.ResponseWriter, r *codec.Request) {
+	r.HandleFunc("eth_*", func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		var res json.RawMessage
 		err = c.Do(r.Context(), &res, r.Method, json.RawMessage(r.Params))
 		w.Send(res, err)
diff --git a/example/subscription/main.go b/example/subscription/main.go
index 698c04121e94430772692f225dc8ffa8d764d81b..2fdd4451f354b3fbdd63523478e54cdc002a19f7 100644
--- a/example/subscription/main.go
+++ b/example/subscription/main.go
@@ -10,7 +10,7 @@ import (
 	"gfx.cafe/open/jrpc/contrib/extension/subscription"
 	"gfx.cafe/open/jrpc/contrib/jmux"
 	"gfx.cafe/open/jrpc/contrib/middleware"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 
 	"gfx.cafe/open/jrpc"
@@ -23,14 +23,14 @@ func main() {
 	r.Use(middleware.Logger)
 	srv := server.NewServer(r)
 
-	r.HandleFunc("echo", func(w codec.ResponseWriter, r *codec.Request) {
+	r.HandleFunc("echo", func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 		w.Send(r.Params, nil)
 	})
 
 	r.Group(func(r jmux.Router) {
 		r.Use(engine.Middleware())
 
-		r.HandleFunc("testservice/subscribe", func(w codec.ResponseWriter, r *codec.Request) {
+		r.HandleFunc("testservice/subscribe", func(w jsonrpc.ResponseWriter, r *jsonrpc.Request) {
 			notifier, ok := subscription.NotifierFromContext(r.Context())
 			if !ok {
 				w.Send(nil, subscription.ErrNotificationsUnsupported)
diff --git a/exports.go b/exports.go
index 37d38bb9ce2fc54abcbfff75cc3d0ae2b0ad4881..7d1953d0b7f1ce9865f2fef98bbbc72141ee73e1 100644
--- a/exports.go
+++ b/exports.go
@@ -4,7 +4,7 @@ import (
 	"context"
 
 	"gfx.cafe/open/jrpc/contrib/codecs"
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -12,31 +12,31 @@ import (
 
 // Conn is used to make requests to jsonrpc2 servers
 type Conn interface {
-	codec.Conn
+	jsonrpc.Conn
 }
 
 // StreamingConn is a conn that supports streaming methods
 type StreamingConn interface {
-	codec.StreamingConn
+	jsonrpc.StreamingConn
 }
 
 // Handler is the equivalent of http.Handler, but for jsonrpc.
-type Handler = codec.Handler
+type Handler = jsonrpc.Handler
 
 // ResponseWriter is used to write responses to the request
-type ResponseWriter = codec.ResponseWriter
+type ResponseWriter = jsonrpc.ResponseWriter
 
 type (
 	// HandlerFunc is a Handler that exists as a function
-	HandlerFunc = codec.HandlerFunc
+	HandlerFunc = jsonrpc.HandlerFunc
 	// Request is the request object
-	Request = codec.Request
+	Request = jsonrpc.Request
 	// Server is a jrpc server
 	Server = server.Server
 	// Middleware is a middleware
 	Middleware = func(Handler) Handler
 	// BatchElem is an element of a batch request
-	BatchElem = codec.BatchElem
+	BatchElem = jsonrpc.BatchElem
 )
 
 var (
@@ -50,25 +50,25 @@ var (
 	Dial = codecs.Dial
 
 	// ContextWithConn will attach a conn to the context
-	ContextWithConn = codec.ContextWithConn
+	ContextWithConn = jsonrpc.ContextWithConn
 	// ContextWithPeerInfo will attach a peerinfo to the context
 	ContextWithPeerInfo = server.ContextWithPeerInfo
 
 	// ConnFromContext will retrieve a conn from context
-	ConnFromContext = codec.ConnFromContext
+	ConnFromContext = jsonrpc.ConnFromContext
 	// PeerInfoFromContext will retrieve a peerinfo from context
 	PeerInfoFromContext = server.PeerInfoFromContext
 )
 
 // Do will use the conn to perform a jsonrpc2 call.
 func Do[T any](ctx context.Context, c Conn, method string, args any) (*T, error) {
-	return codec.Do[T](ctx, c, method, args)
+	return jsonrpc.Do[T](ctx, c, method, args)
 }
 
 // Call will use the conn to perform a jsonrpc2 call, except the args will be encoded as an array of arguments.
 func Call[T any](ctx context.Context, c Conn, method string, args ...any) (*T, error) {
-	return codec.Call[T](ctx, c, method, args...)
+	return jsonrpc.Call[T](ctx, c, method, args...)
 }
 
 // CallInto is the same as Call, except instead of returning, you provide a pointer to the result
-var CallInto = codec.CallInto
+var CallInto = jsonrpc.CallInto
diff --git a/pkg/clientutil/helper.go b/pkg/clientutil/helper.go
index 1519b5b4ddca4bc850d7524459b18b1872486331..962e2f5c572f5c5be56dad2a0463f52d04681fd4 100644
--- a/pkg/clientutil/helper.go
+++ b/pkg/clientutil/helper.go
@@ -6,28 +6,28 @@ import (
 
 	"gfx.cafe/util/go/generic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
-var msgPool = generic.HookPool[*codec.Message]{
-	New: func() *codec.Message {
-		return &codec.Message{}
+var msgPool = generic.HookPool[*jsonrpc.Message]{
+	New: func() *jsonrpc.Message {
+		return &jsonrpc.Message{}
 	},
-	FnPut: func(msg *codec.Message) {
-		*msg = codec.Message{}
+	FnPut: func(msg *jsonrpc.Message) {
+		*msg = jsonrpc.Message{}
 	},
 }
 
-func GetMessage() *codec.Message {
+func GetMessage() *jsonrpc.Message {
 	return msgPool.Get()
 }
 
-func PutMessage(x *codec.Message) {
+func PutMessage(x *jsonrpc.Message) {
 	msgPool.Put(x)
 }
 
-func FillBatch(ids map[int]int, msgs []*codec.Message, b []*codec.BatchElem) {
-	answers := make(map[int]*codec.Message, len(msgs))
+func FillBatch(ids map[int]int, msgs []*jsonrpc.Message, b []*jsonrpc.BatchElem) {
+	answers := make(map[int]*jsonrpc.Message, len(msgs))
 	for _, v := range msgs {
 		answers[v.ID.Number()] = v
 	}
diff --git a/pkg/clientutil/helper_test.go b/pkg/clientutil/helper_test.go
index 134cda58f1e5559857ef2adada39cfd83bcc6c92..1519b2690625473c2fe3b697e3c9c0b0c1d54c0e 100644
--- a/pkg/clientutil/helper_test.go
+++ b/pkg/clientutil/helper_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 func ptr[T any](v T) *T {
@@ -14,19 +14,19 @@ func ptr[T any](v T) *T {
 }
 
 func TestFillBatch(t *testing.T) {
-	msgs := []*codec.Message{
+	msgs := []*jsonrpc.Message{
 		{
-			ID:     ptr(codec.ID(`"5"`)),
-			Result: codec.NewStringReader(`["test", "abc", "123"]`),
+			ID:     ptr(jsonrpc.ID(`"5"`)),
+			Result: jsonrpc.NewStringReader(`["test", "abc", "123"]`),
 		},
 		{
-			ID:     ptr(codec.ID(`"6"`)),
-			Result: codec.NewStringReader(`12345`),
+			ID:     ptr(jsonrpc.ID(`"6"`)),
+			Result: jsonrpc.NewStringReader(`12345`),
 		},
 		{},
 		{
-			ID:     ptr(codec.ID(`"7"`)),
-			Result: codec.NewStringReader(`"abcdefgh"`),
+			ID:     ptr(jsonrpc.ID(`"7"`)),
+			Result: jsonrpc.NewStringReader(`"abcdefgh"`),
 		},
 	}
 	ids := map[int]int{
@@ -34,7 +34,7 @@ func TestFillBatch(t *testing.T) {
 		1: 6,
 		3: 7,
 	}
-	b := []*codec.BatchElem{
+	b := []*jsonrpc.BatchElem{
 		{
 			Result: new([]string),
 		},
@@ -49,7 +49,7 @@ func TestFillBatch(t *testing.T) {
 
 	FillBatch(ids, msgs, b)
 
-	wantResult := []*codec.BatchElem{
+	wantResult := []*jsonrpc.BatchElem{
 		{
 			Result: &[]string{
 				"test",
diff --git a/pkg/clientutil/idreply.go b/pkg/clientutil/idreply.go
index f30fefe0bda66850237354672dbc96482ce655e1..46ebcc1504aa37e8c669a421027644087a02a633 100644
--- a/pkg/clientutil/idreply.go
+++ b/pkg/clientutil/idreply.go
@@ -6,7 +6,7 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type IdReply struct {
@@ -27,8 +27,8 @@ func NewIdReply() *IdReply {
 	}
 }
 
-func (i *IdReply) NextId() *codec.ID {
-	return codec.NewNumberIDPtr(i.id.Add(1))
+func (i *IdReply) NextId() *jsonrpc.ID {
+	return jsonrpc.NewNumberIDPtr(i.id.Add(1))
 }
 
 func (i *IdReply) makeOrTake(id []byte) chan msgOrError {
diff --git a/pkg/clientutil/idreply_test.go b/pkg/clientutil/idreply_test.go
index a0ced8d1790b75101f8adbbdf4a68d5b0a41b2ef..d7a5c61e45329ca8fdb36d522d41fae4e06db7f4 100644
--- a/pkg/clientutil/idreply_test.go
+++ b/pkg/clientutil/idreply_test.go
@@ -6,7 +6,7 @@ import (
 	"sync"
 	"testing"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"github.com/stretchr/testify/require"
 )
 
@@ -38,7 +38,7 @@ func TestIdReply(t *testing.T) {
 
 	for i := 0; i < count; i++ {
 		go func(id int) {
-			reply.Resolve(codec.NewNumberID(int64(id+1)), codec.NewStringReader(testMessage), nil)
+			reply.Resolve(jsonrpc.NewNumberID(int64(id+1)), jsonrpc.NewStringReader(testMessage), nil)
 		}(i)
 	}
 
diff --git a/pkg/codec/json_test.go b/pkg/codec/json_test.go
deleted file mode 100644
index 1fae45a0c875bb63d4aa119672249a233ea9cc52..0000000000000000000000000000000000000000
--- a/pkg/codec/json_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package codec
diff --git a/pkg/jrpctest/services.go b/pkg/jrpctest/services.go
index fe668b5fac1aaa1d2372c82c36c6eb2630ffb4dd..15b7a682b48c67c87bfb1dc5277bf66b43a96258 100644
--- a/pkg/jrpctest/services.go
+++ b/pkg/jrpctest/services.go
@@ -6,7 +6,7 @@ import (
 	"strings"
 	"time"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 )
 
@@ -46,7 +46,7 @@ func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *
 	return EchoResult{str, i, args}
 }
 
-func (s *testService) PeerInfo(ctx context.Context) codec.PeerInfo {
+func (s *testService) PeerInfo(ctx context.Context) jsonrpc.PeerInfo {
 	return server.PeerInfoFromContext(ctx)
 }
 
@@ -81,7 +81,7 @@ func (s *testService) ReturnError() error {
 }
 
 func (s *testService) CallMeBack(ctx context.Context, method string, args []any) (any, error) {
-	c, ok := codec.ConnFromContext(ctx)
+	c, ok := jsonrpc.ConnFromContext(ctx)
 	if !ok {
 		return nil, errors.New("no client")
 	}
@@ -91,7 +91,7 @@ func (s *testService) CallMeBack(ctx context.Context, method string, args []any)
 }
 
 func (s *testService) CallMeBackLater(ctx context.Context, method string, args []any) error {
-	c, ok := codec.ConnFromContext(ctx)
+	c, ok := jsonrpc.ConnFromContext(ctx)
 	if !ok {
 		return errors.New("no client")
 	}
diff --git a/pkg/jrpctest/suites.go b/pkg/jrpctest/suites.go
index 967efbf19bc7cd0ea5d243f244d5c358390b4cac..2630d2cf775dec4163211e9bcf3f1a186e00ae66 100644
--- a/pkg/jrpctest/suites.go
+++ b/pkg/jrpctest/suites.go
@@ -9,22 +9,22 @@ import (
 	"testing"
 	"time"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"gfx.cafe/open/jrpc/pkg/server"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
-type ClientMaker func() codec.Conn
+type ClientMaker func() jsonrpc.Conn
 type ServerMaker func() (*server.Server, ClientMaker, func())
 
 type BasicTestSuiteArgs struct {
 	ServerMaker ServerMaker
 }
 
-type TestContext func(t *testing.T, server *server.Server, client codec.Conn)
-type BenchContext func(t *testing.B, server *server.Server, client codec.Conn)
+type TestContext func(t *testing.T, server *server.Server, client jsonrpc.Conn)
+type BenchContext func(t *testing.B, server *server.Server, client jsonrpc.Conn)
 
 func TestExecutor(sm ServerMaker) func(t *testing.T, c TestContext) {
 	return func(t *testing.T, c TestContext) {
@@ -58,7 +58,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 	}
 
 	t.Parallel()
-	makeTest("Request", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("Request", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 		var resp EchoResult
 		err := client.Do(nil, &resp, "test_echo", []any{"hello", 10, &EchoArgs{"world"}})
 		require.NoError(t, err)
@@ -67,17 +67,17 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 		}
 	})
 
-	makeTest("ResponseType", func(t *testing.T, server *server.Server, client codec.Conn) {
-		err := codec.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"})
+	makeTest("ResponseType", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
+		err := jsonrpc.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"})
 		assert.NoErrorf(t, err, "passing nil as result should be ok")
 		var resultVar EchoResult
 		// Note: passing the var, not a ref
-		err = codec.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"})
+		err = jsonrpc.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"})
 		assert.Error(t, err, "passing var as nil gives error")
 	})
 
-	makeTest("BatchRequest", func(t *testing.T, server *server.Server, client codec.Conn) {
-		batch := []*codec.BatchElem{
+	makeTest("BatchRequest", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
+		batch := []*jsonrpc.BatchElem{
 			{
 				Method: "test_echo",
 				Params: []any{"hello", 10, &EchoArgs{"world"}},
@@ -102,7 +102,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 		if err := client.BatchCall(nil, batch...); err != nil {
 			t.Fatal(err)
 		}
-		wantResult := []*codec.BatchElem{
+		wantResult := []*jsonrpc.BatchElem{
 			{
 				Method: "test_echo",
 				Params: []any{"hello", 10, &EchoArgs{"world"}},
@@ -121,7 +121,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 				Method: "no/such/method",
 				Params: []any{1, 2, 3},
 				Result: new(int),
-				Error:  &codec.JsonError{Code: -32601, Message: "the method no/such/method does not exist/is not available"},
+				Error:  &jsonrpc.JsonError{Code: -32601, Message: "the method no/such/method does not exist/is not available"},
 			},
 		}
 		require.EqualValues(t, len(batch), len(wantResult))
@@ -135,45 +135,45 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 		}
 	})
 
-	makeTest("ResposeType2", func(t *testing.T, server *server.Server, client codec.Conn) {
-		if err := codec.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil {
+	makeTest("ResposeType2", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
+		if err := jsonrpc.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil {
 			t.Errorf("Passing nil as result should be fine, but got an error: %v", err)
 		}
 		var resultVar EchoResult
 		// Note: passing the var, not a ref
-		err := codec.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"})
+		err := jsonrpc.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"})
 		if err == nil {
 			t.Error("Passing a var as result should be an error")
 		}
 	})
 
-	makeTest("ErrorReturnType", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("ErrorReturnType", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 		var resp any
-		err := codec.CallInto(nil, client, &resp, "test_returnError")
+		err := jsonrpc.CallInto(nil, client, &resp, "test_returnError")
 		require.Error(t, err)
 
 		// Check code.
-		if e, ok := err.(codec.Error); !ok {
+		if e, ok := err.(jsonrpc.Error); !ok {
 			t.Fatalf("client did not return rpc.Error, got %#v", e)
 		} else if e.ErrorCode() != (testError{}.ErrorCode()) {
 			t.Fatalf("wrong error code %d, want %d", e.ErrorCode(), testError{}.ErrorCode())
 		}
 		// Check data.
-		if e, ok := err.(codec.DataError); !ok {
+		if e, ok := err.(jsonrpc.DataError); !ok {
 			t.Fatalf("client did not return rpc.DataError, got %#v", e)
 		} else if e.ErrorData() != (testError{}.ErrorData()) {
 			t.Fatalf("wrong error data %#v, want %#v", e.ErrorData(), testError{}.ErrorData())
 		}
 	})
-	makeTest("Notify", func(t *testing.T, server *server.Server, client codec.Conn) {
-		if c, ok := client.(codec.StreamingConn); ok {
+	makeTest("Notify", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
+		if c, ok := client.(jsonrpc.StreamingConn); ok {
 			if err := c.Notify(context.Background(), "test_echo", []any{"hello", 10, &EchoArgs{"world"}}); err != nil {
 				t.Fatal(err)
 			}
 		}
 	})
 
-	makeTest("context cancel", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("context cancel", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 		maxContextCancelTimeout := 300 * time.Millisecond
 		// The actual test starts here.
 		var (
@@ -203,7 +203,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 
 				// Now perform a call with the context.
 				// The key thing here is that no call will ever complete successfully.
-				err := codec.CallInto(ctx, client, nil, "test_block")
+				err := jsonrpc.CallInto(ctx, client, nil, "test_block")
 				switch {
 				case err == nil:
 					_, hasDeadline := ctx.Deadline()
@@ -221,7 +221,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 		wg.Wait()
 	})
 
-	makeTest("big", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("big", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 		var (
 			wg       sync.WaitGroup
 			nreqs    = 2
@@ -234,7 +234,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 				defer wg.Done()
 
 				for j := 0; j < nreqs; j++ {
-					if err := codec.CallInto(context.Background(), client, nil, "large_largeResp"); err != nil {
+					if err := jsonrpc.CallInto(context.Background(), client, nil, "large_largeResp"); err != nil {
 						t.Error(err)
 						return
 					}
@@ -245,6 +245,6 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) {
 		wg.Wait()
 	})
 
-	makeTest("", func(t *testing.T, server *server.Server, client codec.Conn) {
+	makeTest("", func(t *testing.T, server *server.Server, client jsonrpc.Conn) {
 	})
 }
diff --git a/pkg/codec/context.go b/pkg/jsonrpc/context.go
similarity index 97%
rename from pkg/codec/context.go
rename to pkg/jsonrpc/context.go
index 9811f272ebab4adbec82b79277962e0be8972bac..9187fc1c64a395e804a48e562facdd8bf4dd44b1 100644
--- a/pkg/codec/context.go
+++ b/pkg/jsonrpc/context.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import "context"
 
diff --git a/pkg/codec/context_test.go b/pkg/jsonrpc/context_test.go
similarity index 96%
rename from pkg/codec/context_test.go
rename to pkg/jsonrpc/context_test.go
index 8dbaaff7a66a60267ac777c627b79817320b7805..49f935975bed9badbfc614bf5c3f80f112c51409 100644
--- a/pkg/codec/context_test.go
+++ b/pkg/jsonrpc/context_test.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"context"
diff --git a/pkg/codec/dummy.go b/pkg/jsonrpc/dummy.go
similarity index 97%
rename from pkg/codec/dummy.go
rename to pkg/jsonrpc/dummy.go
index 5f7a36f498712f3dd1b9a6315dfb130c2df540fb..548f49d716bf1633145977a614ee9032194280e0 100644
--- a/pkg/codec/dummy.go
+++ b/pkg/jsonrpc/dummy.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import "context"
 
diff --git a/pkg/codec/errors.go b/pkg/jsonrpc/errors.go
similarity index 99%
rename from pkg/codec/errors.go
rename to pkg/jsonrpc/errors.go
index ec8c092f6467968e3ded5f0f5f2d629e342272c6..4757c9431a97e42dd7a0ae493ebedcb6514ec2e6 100644
--- a/pkg/codec/errors.go
+++ b/pkg/jsonrpc/errors.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"encoding/json"
diff --git a/pkg/codec/helper.go b/pkg/jsonrpc/helper.go
similarity index 97%
rename from pkg/codec/helper.go
rename to pkg/jsonrpc/helper.go
index 491ef956bfe6f355bcb679babbffc30801b06974..f4f49c3bb7b4b460f8cc5de1400a56f3de315dc9 100644
--- a/pkg/codec/helper.go
+++ b/pkg/jsonrpc/helper.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import "context"
 
diff --git a/pkg/codec/jrpc.go b/pkg/jsonrpc/jrpc.go
similarity index 98%
rename from pkg/codec/jrpc.go
rename to pkg/jsonrpc/jrpc.go
index 6f9bd22ba9549157703b90db829cdb5b27fbf97e..c7cb6db238eb40eca84eb59f198920e3f9d8d44f 100644
--- a/pkg/codec/jrpc.go
+++ b/pkg/jsonrpc/jrpc.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"context"
diff --git a/pkg/codec/json.go b/pkg/jsonrpc/json.go
similarity index 99%
rename from pkg/codec/json.go
rename to pkg/jsonrpc/json.go
index 2c0dca29efb939117da9c962e27afaa18c3be576..5935de73df342a01bf639cef4c7e68bf2e1a4244 100644
--- a/pkg/codec/json.go
+++ b/pkg/jsonrpc/json.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"bytes"
diff --git a/pkg/jsonrpc/json_test.go b/pkg/jsonrpc/json_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..29a4d6abae9269d8df4359218dd6fff43f4711ce
--- /dev/null
+++ b/pkg/jsonrpc/json_test.go
@@ -0,0 +1 @@
+package jsonrpc
diff --git a/pkg/codec/middleware.go b/pkg/jsonrpc/middleware.go
similarity index 99%
rename from pkg/codec/middleware.go
rename to pkg/jsonrpc/middleware.go
index 9ce22830789729f47acf30b35fbc2d202d18c91c..8009b1f433e64249aeaffdb12d0fe63732f3a2a3 100644
--- a/pkg/codec/middleware.go
+++ b/pkg/jsonrpc/middleware.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 type Middleware = func(Handler) Handler
 
diff --git a/pkg/codec/peer.go b/pkg/jsonrpc/peer.go
similarity index 97%
rename from pkg/codec/peer.go
rename to pkg/jsonrpc/peer.go
index 32ab3eeaf3b89ed72e15fd4dd59eaefa29e60033..b0c2cf794df4552c46385baddf3f4affc13d67ab 100644
--- a/pkg/codec/peer.go
+++ b/pkg/jsonrpc/peer.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"net/http"
diff --git a/pkg/codec/reqresp.go b/pkg/jsonrpc/reqresp.go
similarity index 99%
rename from pkg/codec/reqresp.go
rename to pkg/jsonrpc/reqresp.go
index 3ceb677222eaa6929e73e7591141d2fd341a9e1e..4358225068900d3a53d847d7beef4cad2ed7be8e 100644
--- a/pkg/codec/reqresp.go
+++ b/pkg/jsonrpc/reqresp.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"context"
diff --git a/pkg/codec/transport.go b/pkg/jsonrpc/transport.go
similarity index 98%
rename from pkg/codec/transport.go
rename to pkg/jsonrpc/transport.go
index 8291413c05483178b29aec5fd952e1b26f69649f..8a33f22390f7d6d9af598c72073b3637d21d1169 100644
--- a/pkg/codec/transport.go
+++ b/pkg/jsonrpc/transport.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"context"
diff --git a/pkg/codec/wire.go b/pkg/jsonrpc/wire.go
similarity index 99%
rename from pkg/codec/wire.go
rename to pkg/jsonrpc/wire.go
index 4a9c19cde29b3cd7f22253ddac3fd39370d2b7ef..b844d5a353bf9229539eec956433c8d7f88af72d 100644
--- a/pkg/codec/wire.go
+++ b/pkg/jsonrpc/wire.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"bytes"
diff --git a/pkg/codec/wire_test.go b/pkg/jsonrpc/wire_test.go
similarity index 99%
rename from pkg/codec/wire_test.go
rename to pkg/jsonrpc/wire_test.go
index 900a90ad4c9c4b641a6d9703d193e010f272472a..95924ea684bbba13c88aa86bf7757b2086d995d2 100644
--- a/pkg/codec/wire_test.go
+++ b/pkg/jsonrpc/wire_test.go
@@ -1,4 +1,4 @@
-package codec
+package jsonrpc
 
 import (
 	"encoding/json"
diff --git a/pkg/server/responsewriter.go b/pkg/server/responsewriter.go
index 5367ae454d04c29ee2b6e26f417b06de2d14b25a..09a7dff2c23441032bf5b438420b1cc2e7fac5f1 100644
--- a/pkg/server/responsewriter.go
+++ b/pkg/server/responsewriter.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"sync"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 // 16mb... should be more than enough for any batch.
@@ -12,12 +12,12 @@ import (
 // TODO: make this configurable
 const maxBatchSizeBytes = 1024 * 1024 * 1024 * 16
 
-var _ codec.ResponseWriter = (*streamingRespWriter)(nil)
+var _ jsonrpc.ResponseWriter = (*streamingRespWriter)(nil)
 
 // streamingRespWriter is NOT thread safe
 type streamingRespWriter struct {
 	cr  *callResponder
-	msg *codec.Message
+	msg *jsonrpc.Message
 	ctx context.Context
 
 	err error
@@ -31,10 +31,10 @@ func (c *streamingRespWriter) Send(v any, e error) (err error) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	if c.msg.ID == nil {
-		return codec.ErrCantSendNotification
+		return jsonrpc.ErrCantSendNotification
 	}
 	if c.sendCalled {
-		return codec.ErrSendAlreadyCalled
+		return jsonrpc.ErrSendAlreadyCalled
 	}
 	c.sendCalled = true
 	ce := &callEnv{
@@ -67,7 +67,7 @@ func (c *streamingRespWriter) Send(v any, e error) (err error) {
 	return nil
 }
 
-func (c *streamingRespWriter) ExtraFields() codec.ExtraFields {
+func (c *streamingRespWriter) ExtraFields() jsonrpc.ExtraFields {
 	return c.msg.ExtraFields
 }
 
diff --git a/pkg/server/rw_batch.go b/pkg/server/rw_batch.go
index ce7fbe01e96fa6c0de7d8e4c3157e94cb996ece1..e3073bf8417b4d8763600f93b28c7eed5cb3bfeb 100644
--- a/pkg/server/rw_batch.go
+++ b/pkg/server/rw_batch.go
@@ -5,14 +5,14 @@ import (
 	"context"
 	"sync"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"github.com/goccy/go-json"
 )
 
 // batchingRespWriter is NOT thread safe
 type batchingRespWriter struct {
 	cr  *callResponder
-	msg *codec.Message
+	msg *jsonrpc.Message
 	ctx context.Context
 
 	wg      *sync.WaitGroup
@@ -28,10 +28,10 @@ func (c *batchingRespWriter) Send(v any, e error) (err error) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	if c.msg.ID == nil {
-		return codec.ErrCantSendNotification
+		return jsonrpc.ErrCantSendNotification
 	}
 	if c.sendCalled {
-		return codec.ErrSendAlreadyCalled
+		return jsonrpc.ErrSendAlreadyCalled
 	}
 	c.sendCalled = true
 	if c.wg != nil {
@@ -51,7 +51,7 @@ func (c *batchingRespWriter) Send(v any, e error) (err error) {
 		err = json.NewEncoder(w).Encode(v)
 		if err != nil {
 			// the user just gets a generic error saying that the json is bad
-			c.err = codec.NewInternalError("server sent bad json")
+			c.err = jsonrpc.NewInternalError("server sent bad json")
 			// json marshaling errors are reported to the Send call, not the user
 			return err
 		}
@@ -61,7 +61,7 @@ func (c *batchingRespWriter) Send(v any, e error) (err error) {
 	return nil
 }
 
-func (c *batchingRespWriter) ExtraFields() codec.ExtraFields {
+func (c *batchingRespWriter) ExtraFields() jsonrpc.ExtraFields {
 	return c.msg.ExtraFields
 }
 
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 4e88eaa53f0d54af7751393d72f344f38f513eb2..2139d548d5955a1e0bc022bbf4a72fae4b170db7 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -5,7 +5,7 @@ import (
 	"errors"
 	"sync"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 	"golang.org/x/sync/semaphore"
 
 	"gfx.cafe/util/go/bufpool"
@@ -18,14 +18,14 @@ import (
 // it is in charge of calling the handler on the message object, the json encoding of responses, and dealing with batch semantics.
 // a server can be used to listenandserve multiple codecs at a time
 type Server struct {
-	services codec.Handler
+	services jsonrpc.Handler
 
 	lctx context.Context
 	cn   context.CancelFunc
 }
 
 // NewServer creates a new server instance with no registered handlers.
-func NewServer(r codec.Handler) *Server {
+func NewServer(r jsonrpc.Handler) *Server {
 	server := &Server{services: r}
 	server.lctx, server.cn = context.WithCancel(context.Background())
 	return server
@@ -33,7 +33,7 @@ func NewServer(r codec.Handler) *Server {
 
 // ServeCodec reads incoming requests from codec, calls the appropriate callback and writes
 // the response back using the given codec. It will block until the codec is closed
-func (s *Server) ServeCodec(ctx context.Context, remote codec.ReaderWriter) error {
+func (s *Server) ServeCodec(ctx context.Context, remote jsonrpc.ReaderWriter) error {
 	defer remote.Close()
 
 	sema := semaphore.NewWeighted(1)
@@ -81,7 +81,7 @@ func (s *Server) Shutdown(ctx context.Context) {
 }
 
 func (s *Server) serve(ctx context.Context,
-	incoming []*codec.Message,
+	incoming []*jsonrpc.Message,
 	r *callResponder,
 ) error {
 	if r.batch {
@@ -92,7 +92,7 @@ func (s *Server) serve(ctx context.Context,
 }
 
 func (s *Server) serveSingle(ctx context.Context,
-	incoming *codec.Message,
+	incoming *jsonrpc.Message,
 	r *callResponder,
 ) error {
 	rw := &streamingRespWriter{
@@ -100,7 +100,7 @@ func (s *Server) serveSingle(ctx context.Context,
 		cr:  r,
 	}
 	rw.msg, rw.err = produceOutputMessage(incoming)
-	req := codec.NewRequestFromMessage(
+	req := jsonrpc.NewRequestFromMessage(
 		ctx,
 		rw.msg,
 	)
@@ -119,35 +119,35 @@ func (s *Server) serveSingle(ctx context.Context,
 	}
 	s.services.ServeRPC(rw, req)
 	if rw.sendCalled == false && rw.msg.ID != nil {
-		rw.Send(codec.Null, nil)
+		rw.Send(jsonrpc.Null, nil)
 	}
 	return nil
 }
 
-func produceOutputMessage(inputMessage *codec.Message) (out *codec.Message, err error) {
+func produceOutputMessage(inputMessage *jsonrpc.Message) (out *jsonrpc.Message, err error) {
 	// a nil incoming message means return an invalid request.
 	if inputMessage == nil {
-		inputMessage = &codec.Message{ID: codec.NewNullIDPtr()}
-		err = codec.NewInvalidRequestError("invalid request")
+		inputMessage = &jsonrpc.Message{ID: jsonrpc.NewNullIDPtr()}
+		err = jsonrpc.NewInvalidRequestError("invalid request")
 	}
 	out = inputMessage
-	out.ExtraFields = codec.ExtraFields{}
+	out.ExtraFields = jsonrpc.ExtraFields{}
 	out.Error = nil
 	// zero length method is always invalid request
 	if len(out.Method) == 0 {
 		// assume if the method is not there AND the id is not there that it's an invalid REQUEST not notification
 		// this makes sure we add 1 to totalRequests
 		if out.ID == nil {
-			out.ID = codec.NewNullIDPtr()
+			out.ID = jsonrpc.NewNullIDPtr()
 		}
-		err = codec.NewInvalidRequestError("invalid request")
+		err = jsonrpc.NewInvalidRequestError("invalid request")
 	}
 
 	return
 }
 
 func (s *Server) serveBatch(ctx context.Context,
-	incoming []*codec.Message,
+	incoming []*jsonrpc.Message,
 	r *callResponder,
 ) error {
 	// check for empty batch
@@ -159,8 +159,8 @@ func (s *Server) serveBatch(ctx context.Context,
 		}
 		defer r.mu.Release(1)
 		err = r.send(ctx, &callEnv{
-			id:  codec.NewNullIDPtr(),
-			err: codec.NewInvalidRequestError("empty batch"),
+			id:  jsonrpc.NewNullIDPtr(),
+			err: jsonrpc.NewInvalidRequestError("empty batch"),
 		})
 		if err != nil {
 			return err
@@ -210,14 +210,14 @@ func (s *Server) serveBatch(ctx context.Context,
 		// TODO: stress test this.
 		go func() {
 			defer returnWg.Done()
-			req := codec.NewRequestFromMessage(
+			req := jsonrpc.NewRequestFromMessage(
 				ctx,
 				v.msg,
 			)
 			req.Peer = peerInfo
 			s.services.ServeRPC(v, req)
 			if v.sendCalled == false && v.err == nil {
-				v.Send(codec.Null, nil)
+				v.Send(jsonrpc.Null, nil)
 			}
 		}()
 	}
@@ -276,7 +276,7 @@ func (s *Server) serveBatch(ctx context.Context,
 }
 
 type callResponder struct {
-	remote codec.ReaderWriter
+	remote jsonrpc.ReaderWriter
 	mu     *semaphore.Weighted
 
 	batch        bool
@@ -286,8 +286,8 @@ type callResponder struct {
 type callEnv struct {
 	v           any
 	err         error
-	id          *codec.ID
-	extrafields codec.ExtraFields
+	id          *jsonrpc.ID
+	extrafields jsonrpc.ExtraFields
 }
 
 func (c *callResponder) send(ctx context.Context, env *callEnv) (err error) {
@@ -313,7 +313,7 @@ func (c *callResponder) send(ctx context.Context, env *callEnv) (err error) {
 		}
 		if env.err != nil {
 			e.Field("error", func(e *jx.Encoder) {
-				codec.EncodeError(e, env.err)
+				jsonrpc.EncodeError(e, env.err)
 			})
 		} else {
 			// if there is no error, we try to marshal the result
@@ -354,11 +354,11 @@ func (c *callResponder) send(ctx context.Context, env *callEnv) (err error) {
 type notifyEnv struct {
 	method string
 	dat    any
-	extra  codec.ExtraFields
+	extra  jsonrpc.ExtraFields
 }
 
 func (c *callResponder) notify(ctx context.Context, env *notifyEnv) (err error) {
-	msg := &codec.Message{}
+	msg := &jsonrpc.Message{}
 	//  allocate a temp buffer for this packet
 	buf := bufpool.GetStd()
 	defer bufpool.PutStd(buf)
@@ -375,7 +375,7 @@ func (c *callResponder) notify(ctx context.Context, env *notifyEnv) (err error)
 	defer jx.PutEncoder(enc)
 	enc.Grow(4096)
 	enc.ResetWriter(c.remote)
-	err = codec.MarshalMessage(msg, enc)
+	err = jsonrpc.MarshalMessage(msg, enc)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/server/util.go b/pkg/server/util.go
index 796482efd45bdf0bd332e541fd08fc01c20fbddf..b405962a5cf399d7422d226727d685d46f1596ce 100644
--- a/pkg/server/util.go
+++ b/pkg/server/util.go
@@ -3,7 +3,7 @@ package server
 import (
 	"context"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type peerInfoContextKey struct{}
@@ -12,10 +12,10 @@ type peerInfoContextKey struct{}
 // Use this with the context passed to RPC method handler functions.
 //
 // The zero value is returned if no connection info is present in ctx.
-func PeerInfoFromContext(ctx context.Context) codec.PeerInfo {
-	info, _ := ctx.Value(peerInfoContextKey{}).(codec.PeerInfo)
+func PeerInfoFromContext(ctx context.Context) jsonrpc.PeerInfo {
+	info, _ := ctx.Value(peerInfoContextKey{}).(jsonrpc.PeerInfo)
 	return info
 }
-func ContextWithPeerInfo(ctx context.Context, c codec.PeerInfo) context.Context {
+func ContextWithPeerInfo(ctx context.Context, c jsonrpc.PeerInfo) context.Context {
 	return context.WithValue(ctx, peerInfoContextKey{}, c)
 }
diff --git a/pkg/serverutil/msg.go b/pkg/serverutil/msg.go
index 209f9b3a37d56f65ab0524beacf1429b3c1da617..bc8da1df3c6708907c9deb9b555aedf716f37b4e 100644
--- a/pkg/serverutil/msg.go
+++ b/pkg/serverutil/msg.go
@@ -3,16 +3,16 @@ package serverutil
 import (
 	"encoding/json"
 
-	"gfx.cafe/open/jrpc/pkg/codec"
+	"gfx.cafe/open/jrpc/pkg/jsonrpc"
 )
 
 type Bundle struct {
-	Messages []*codec.Message
+	Messages []*jsonrpc.Message
 	Batch    bool
 }
 
 func ParseBundle(raw json.RawMessage) *Bundle {
-	a, b := codec.ParseMessage(raw)
+	a, b := jsonrpc.ParseMessage(raw)
 	return &Bundle{
 		Messages: a,
 		Batch:    b,