Skip to content

Commit bfa5e30

Browse files
authored
jsonrpc: package with JSON-RPC symbols (#117)
Move the aliases to the internal/jsonrpc2 package into their own package. Fixes #115.
1 parent 2c577e5 commit bfa5e30

File tree

9 files changed

+112
-95
lines changed

9 files changed

+112
-95
lines changed

jsonrpc/jsonrpc.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
2+
// Use of this source code is governed by an MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package jsonrpc exposes part of a JSON-RPC v2 implementation
6+
// for use by mcp transport authors.
7+
package jsonrpc
8+
9+
import "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
10+
11+
type (
12+
// ID is a JSON-RPC request ID.
13+
ID = jsonrpc2.ID
14+
// Message is a JSON-RPC message.
15+
Message = jsonrpc2.Message
16+
// Request is a JSON-RPC request.
17+
Request = jsonrpc2.Request
18+
// Response is a JSON-RPC response.
19+
Response = jsonrpc2.Response
20+
)

mcp/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
16+
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
1617
)
1718

1819
// A Client is an MCP client, which may be connected to an MCP server
@@ -301,7 +302,7 @@ func (cs *ClientSession) receivingMethodInfos() map[string]methodInfo {
301302
return clientMethodInfos
302303
}
303304

304-
func (cs *ClientSession) handle(ctx context.Context, req *JSONRPCRequest) (any, error) {
305+
func (cs *ClientSession) handle(ctx context.Context, req *jsonrpc.Request) (any, error) {
305306
return handleReceive(ctx, cs, req)
306307
}
307308

mcp/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
2323
"github.com/modelcontextprotocol/go-sdk/internal/util"
24+
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
2425
)
2526

2627
const DefaultPageSize = 1000
@@ -610,7 +611,7 @@ func (ss *ServerSession) receivingMethodHandler() methodHandler {
610611
func (ss *ServerSession) getConn() *jsonrpc2.Connection { return ss.conn }
611612

612613
// handle invokes the method described by the given JSON RPC request.
613-
func (ss *ServerSession) handle(ctx context.Context, req *JSONRPCRequest) (any, error) {
614+
func (ss *ServerSession) handle(ctx context.Context, req *jsonrpc.Request) (any, error) {
614615
ss.mu.Lock()
615616
initialized := ss.initialized
616617
ss.mu.Unlock()

mcp/shared.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"time"
2121

2222
"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
23+
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
2324
)
2425

2526
// latestProtocolVersion is the latest protocol version that this version of the SDK supports.
@@ -121,7 +122,7 @@ func defaultReceivingMethodHandler[S Session](ctx context.Context, session S, me
121122
return info.handleMethod.(MethodHandler[S])(ctx, session, method, params)
122123
}
123124

124-
func handleReceive[S Session](ctx context.Context, session S, req *JSONRPCRequest) (Result, error) {
125+
func handleReceive[S Session](ctx context.Context, session S, req *jsonrpc.Request) (Result, error) {
125126
info, ok := session.receivingMethodInfos()[req.Method]
126127
if !ok {
127128
return nil, jsonrpc2.ErrNotHandled

mcp/sse.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"sync"
1919

2020
"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
21+
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
2122
)
2223

2324
// This file implements support for SSE (HTTP with server-sent events)
@@ -111,7 +112,7 @@ func NewSSEHandler(getServer func(request *http.Request) *Server) *SSEHandler {
111112
// - Close terminates the hanging GET.
112113
type SSEServerTransport struct {
113114
endpoint string
114-
incoming chan JSONRPCMessage // queue of incoming messages; never closed
115+
incoming chan jsonrpc.Message // queue of incoming messages; never closed
115116

116117
// We must guard both pushes to the incoming queue and writes to the response
117118
// writer, because incoming POST requests are arbitrarily concurrent and we
@@ -138,7 +139,7 @@ func NewSSEServerTransport(endpoint string, w http.ResponseWriter) *SSEServerTra
138139
return &SSEServerTransport{
139140
endpoint: endpoint,
140141
w: w,
141-
incoming: make(chan JSONRPCMessage, 100),
142+
incoming: make(chan jsonrpc.Message, 100),
142143
done: make(chan struct{}),
143144
}
144145
}
@@ -267,7 +268,7 @@ type sseServerConn struct {
267268
func (s sseServerConn) SessionID() string { return "" }
268269

269270
// Read implements jsonrpc2.Reader.
270-
func (s sseServerConn) Read(ctx context.Context) (JSONRPCMessage, error) {
271+
func (s sseServerConn) Read(ctx context.Context) (jsonrpc.Message, error) {
271272
select {
272273
case <-ctx.Done():
273274
return nil, ctx.Err()
@@ -279,7 +280,7 @@ func (s sseServerConn) Read(ctx context.Context) (JSONRPCMessage, error) {
279280
}
280281

281282
// Write implements jsonrpc2.Writer.
282-
func (s sseServerConn) Write(ctx context.Context, msg JSONRPCMessage) error {
283+
func (s sseServerConn) Write(ctx context.Context, msg jsonrpc.Message) error {
283284
if ctx.Err() != nil {
284285
return ctx.Err()
285286
}
@@ -532,7 +533,7 @@ func (c *sseClientConn) isDone() bool {
532533
return c.closed
533534
}
534535

535-
func (c *sseClientConn) Read(ctx context.Context) (JSONRPCMessage, error) {
536+
func (c *sseClientConn) Read(ctx context.Context) (jsonrpc.Message, error) {
536537
select {
537538
case <-ctx.Done():
538539
return nil, ctx.Err()
@@ -553,7 +554,7 @@ func (c *sseClientConn) Read(ctx context.Context) (JSONRPCMessage, error) {
553554
}
554555
}
555556

556-
func (c *sseClientConn) Write(ctx context.Context, msg JSONRPCMessage) error {
557+
func (c *sseClientConn) Write(ctx context.Context, msg jsonrpc.Message) error {
557558
data, err := jsonrpc2.EncodeMessage(msg)
558559
if err != nil {
559560
return err

mcp/streamable.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"sync/atomic"
1717

1818
"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2"
19+
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
1920
)
2021

2122
const (
@@ -157,12 +158,12 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
157158
func NewStreamableServerTransport(sessionID string) *StreamableServerTransport {
158159
return &StreamableServerTransport{
159160
id: sessionID,
160-
incoming: make(chan JSONRPCMessage, 10),
161+
incoming: make(chan jsonrpc.Message, 10),
161162
done: make(chan struct{}),
162163
outgoingMessages: make(map[streamID][]*streamableMsg),
163164
signals: make(map[streamID]chan struct{}),
164-
requestStreams: make(map[JSONRPCID]streamID),
165-
streamRequests: make(map[streamID]map[JSONRPCID]struct{}),
165+
requestStreams: make(map[jsonrpc.ID]streamID),
166+
streamRequests: make(map[streamID]map[jsonrpc.ID]struct{}),
166167
}
167168
}
168169

@@ -176,7 +177,7 @@ type StreamableServerTransport struct {
176177
nextStreamID atomic.Int64 // incrementing next stream ID
177178

178179
id string
179-
incoming chan JSONRPCMessage // messages from the client to the server
180+
incoming chan jsonrpc.Message // messages from the client to the server
180181

181182
mu sync.Mutex
182183

@@ -226,7 +227,7 @@ type StreamableServerTransport struct {
226227
// Lifecycle: requestStreams persists for the duration of the session.
227228
//
228229
// TODO(rfindley): clean up once requests are handled.
229-
requestStreams map[JSONRPCID]streamID
230+
requestStreams map[jsonrpc.ID]streamID
230231

231232
// streamRequests tracks the set of unanswered incoming RPCs for each logical
232233
// stream.
@@ -237,7 +238,7 @@ type StreamableServerTransport struct {
237238
// Lifecycle: streamRequests values persist as until the requests have been
238239
// replied to by the server. Notably, NOT until they are sent to an HTTP
239240
// response, as delivery is not guaranteed.
240-
streamRequests map[streamID]map[JSONRPCID]struct{}
241+
streamRequests map[streamID]map[jsonrpc.ID]struct{}
241242
}
242243

243244
type streamID int64
@@ -271,7 +272,7 @@ func (s *StreamableServerTransport) Connect(context.Context) (Connection, error)
271272
// 2. Expose a 'HandlerTransport' interface that allows transports to provide
272273
// a handler middleware, so that we don't hard-code this behavior in
273274
// ServerSession.handle.
274-
// 3. Add a `func ForRequest(context.Context) JSONRPCID` accessor that lets
275+
// 3. Add a `func ForRequest(context.Context) jsonrpc.ID` accessor that lets
275276
// any transport access the incoming request ID.
276277
//
277278
// For now, by giving only the StreamableServerTransport access to the request
@@ -340,9 +341,9 @@ func (t *StreamableServerTransport) servePOST(w http.ResponseWriter, req *http.R
340341
http.Error(w, fmt.Sprintf("malformed payload: %v", err), http.StatusBadRequest)
341342
return
342343
}
343-
requests := make(map[JSONRPCID]struct{})
344+
requests := make(map[jsonrpc.ID]struct{})
344345
for _, msg := range incoming {
345-
if req, ok := msg.(*JSONRPCRequest); ok && req.ID.IsValid() {
346+
if req, ok := msg.(*jsonrpc.Request); ok && req.ID.IsValid() {
346347
requests[req.ID] = struct{}{}
347348
}
348349
}
@@ -352,7 +353,7 @@ func (t *StreamableServerTransport) servePOST(w http.ResponseWriter, req *http.R
352353
signal := make(chan struct{}, 1)
353354
t.mu.Lock()
354355
if len(requests) > 0 {
355-
t.streamRequests[id] = make(map[JSONRPCID]struct{})
356+
t.streamRequests[id] = make(map[jsonrpc.ID]struct{})
356357
}
357358
for reqID := range requests {
358359
t.requestStreams[reqID] = id
@@ -484,7 +485,7 @@ func parseEventID(eventID string) (sid streamID, idx int, ok bool) {
484485
}
485486

486487
// Read implements the [Connection] interface.
487-
func (t *StreamableServerTransport) Read(ctx context.Context) (JSONRPCMessage, error) {
488+
func (t *StreamableServerTransport) Read(ctx context.Context) (jsonrpc.Message, error) {
488489
select {
489490
case <-ctx.Done():
490491
return nil, ctx.Err()
@@ -499,10 +500,10 @@ func (t *StreamableServerTransport) Read(ctx context.Context) (JSONRPCMessage, e
499500
}
500501

501502
// Write implements the [Connection] interface.
502-
func (t *StreamableServerTransport) Write(ctx context.Context, msg JSONRPCMessage) error {
503+
func (t *StreamableServerTransport) Write(ctx context.Context, msg jsonrpc.Message) error {
503504
// Find the incoming request that this write relates to, if any.
504-
var forRequest, replyTo JSONRPCID
505-
if resp, ok := msg.(*JSONRPCResponse); ok {
505+
var forRequest, replyTo jsonrpc.ID
506+
if resp, ok := msg.(*jsonrpc.Response); ok {
506507
// If the message is a response, it relates to its request (of course).
507508
forRequest = resp.ID
508509
replyTo = resp.ID
@@ -511,7 +512,7 @@ func (t *StreamableServerTransport) Write(ctx context.Context, msg JSONRPCMessag
511512
// ongoing request. This may not be the case if the request way made with
512513
// an unrelated context.
513514
if v := ctx.Value(idContextKey{}); v != nil {
514-
forRequest = v.(JSONRPCID)
515+
forRequest = v.(jsonrpc.ID)
515516
}
516517
}
517518

@@ -661,7 +662,7 @@ func (c *streamableClientConn) SessionID() string {
661662
}
662663

663664
// Read implements the [Connection] interface.
664-
func (s *streamableClientConn) Read(ctx context.Context) (JSONRPCMessage, error) {
665+
func (s *streamableClientConn) Read(ctx context.Context) (jsonrpc.Message, error) {
665666
select {
666667
case <-ctx.Done():
667668
return nil, ctx.Err()
@@ -673,7 +674,7 @@ func (s *streamableClientConn) Read(ctx context.Context) (JSONRPCMessage, error)
673674
}
674675

675676
// Write implements the [Connection] interface.
676-
func (s *streamableClientConn) Write(ctx context.Context, msg JSONRPCMessage) error {
677+
func (s *streamableClientConn) Write(ctx context.Context, msg jsonrpc.Message) error {
677678
s.mu.Lock()
678679
if s.err != nil {
679680
s.mu.Unlock()
@@ -709,7 +710,7 @@ func (s *streamableClientConn) Write(ctx context.Context, msg JSONRPCMessage) er
709710
return nil
710711
}
711712

712-
func (s *streamableClientConn) postMessage(ctx context.Context, sessionID string, msg JSONRPCMessage) (string, error) {
713+
func (s *streamableClientConn) postMessage(ctx context.Context, sessionID string, msg jsonrpc.Message) (string, error) {
713714
data, err := jsonrpc2.EncodeMessage(msg)
714715
if err != nil {
715716
return "", err

0 commit comments

Comments
 (0)