Skip to content

Commit 93a41b2

Browse files
internal/jsonrpc2: remove unused code (#910)
Remove code inherited from x/tools/internal/jsonrpc2_v2 that is not used by MCP transports. MCP transports implement their own framing and connection management, using only the Connection engine and message encode/decode from this package. Removed files: - serve.go: Server, Listener, Dialer, idleListener, Dial, NewServer - net.go: NetListener, NetDialer, NetPipeListener - serve_test.go, jsonrpc2_test.go: tests for removed infrastructure Removed from remaining files: - frame.go: Framer interface, RawFramer, HeaderFramer implementations - conn.go: Binder, BinderFunc, ConnectionOptions, bindConnection - jsonrpc2.go: ErrIdleTimeout, PreempterFunc, defaultHandler, async helper - wire.go: ErrServerOverloaded - conn.go: AsyncCall.IsReady (unused method)
1 parent 446beae commit 93a41b2

8 files changed

Lines changed: 29 additions & 1580 deletions

File tree

internal/jsonrpc2/conn.go

Lines changed: 23 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,6 @@ import (
1616
"github.com/modelcontextprotocol/go-sdk/internal/json"
1717
)
1818

19-
// Binder builds a connection configuration.
20-
// This may be used in servers to generate a new configuration per connection.
21-
// ConnectionOptions itself implements Binder returning itself unmodified, to
22-
// allow for the simple cases where no per connection information is needed.
23-
type Binder interface {
24-
// Bind returns the ConnectionOptions to use when establishing the passed-in
25-
// Connection.
26-
//
27-
// The connection is not ready to use when Bind is called,
28-
// but Bind may close it without reading or writing to it.
29-
Bind(context.Context, *Connection) ConnectionOptions
30-
}
31-
32-
// A BinderFunc implements the Binder interface for a standalone Bind function.
33-
type BinderFunc func(context.Context, *Connection) ConnectionOptions
34-
35-
func (f BinderFunc) Bind(ctx context.Context, c *Connection) ConnectionOptions {
36-
return f(ctx, c)
37-
}
38-
39-
var _ Binder = BinderFunc(nil)
40-
41-
// ConnectionOptions holds the options for new connections.
42-
type ConnectionOptions struct {
43-
// Framer allows control over the message framing and encoding.
44-
// If nil, HeaderFramer will be used.
45-
Framer Framer
46-
// Preempter allows registration of a pre-queue message handler.
47-
// If nil, no messages will be preempted.
48-
Preempter Preempter
49-
// Handler is used as the queued message handler for inbound messages.
50-
// If nil, all responses will be ErrNotHandled.
51-
Handler Handler
52-
// OnInternalError, if non-nil, is called with any internal errors that occur
53-
// while serving the connection, such as protocol errors or invariant
54-
// violations. (If nil, internal errors result in panics.)
55-
OnInternalError func(error)
56-
}
57-
5819
// Connection manages the jsonrpc2 protocol, connecting responses back to their
5920
// calls. Connection is bidirectional; it does not have a designated server or
6021
// client end.
@@ -197,9 +158,28 @@ type incomingRequest struct {
197158
cancel context.CancelFunc
198159
}
199160

200-
// Bind returns the options unmodified.
201-
func (o ConnectionOptions) Bind(context.Context, *Connection) ConnectionOptions {
202-
return o
161+
// Reader abstracts the transport mechanics from the JSON RPC protocol.
162+
// A Connection reads messages from the reader it was provided on construction,
163+
// and assumes that each call to Read fully transfers a single message,
164+
// or returns an error.
165+
//
166+
// A reader is not safe for concurrent use, it is expected it will be used by
167+
// a single Connection in a safe manner.
168+
type Reader interface {
169+
// Read gets the next message from the stream.
170+
Read(context.Context) (Message, error)
171+
}
172+
173+
// Writer abstracts the transport mechanics from the JSON RPC protocol.
174+
// A Connection writes messages using the writer it was provided on construction,
175+
// and assumes that each call to Write fully transfers a single message,
176+
// or returns an error.
177+
//
178+
// A writer must be safe for concurrent use, as writes may occur concurrently
179+
// in practice: libraries may make calls or respond to requests asynchronously.
180+
type Writer interface {
181+
// Write sends a message to the stream.
182+
Write(context.Context, Message) error
203183
}
204184

205185
// A ConnectionConfig configures a bidirectional jsonrpc2 connection.
@@ -230,59 +210,16 @@ func NewConnection(ctx context.Context, cfg ConnectionConfig) *Connection {
230210
return c
231211
}
232212

233-
// bindConnection creates a new connection and runs it.
234-
//
235-
// This is used by the Dial and Serve functions to build the actual connection.
236-
//
237-
// The connection is closed automatically (and its resources cleaned up) when
238-
// the last request has completed after the underlying ReadWriteCloser breaks,
239-
// but it may be stopped earlier by calling Close (for a clean shutdown).
240-
func bindConnection(bindCtx context.Context, rwc io.ReadWriteCloser, binder Binder, onDone func()) *Connection {
241-
// TODO: Should we create a new event span here?
242-
// This will propagate cancellation from ctx; should it?
243-
ctx := notDone{bindCtx}
244-
245-
c := &Connection{
246-
state: inFlightState{closer: rwc},
247-
done: make(chan struct{}),
248-
onDone: onDone,
249-
}
250-
// It's tempting to set a finalizer on c to verify that the state has gone
251-
// idle when the connection becomes unreachable. Unfortunately, the Binder
252-
// interface makes that unsafe: it allows the Handler to close over the
253-
// Connection, which could create a reference cycle that would cause the
254-
// Connection to become uncollectable.
255-
256-
options := binder.Bind(bindCtx, c)
257-
framer := options.Framer
258-
if framer == nil {
259-
framer = HeaderFramer()
260-
}
261-
c.handler = options.Handler
262-
if c.handler == nil {
263-
c.handler = defaultHandler{}
264-
}
265-
c.onInternalError = options.OnInternalError
266-
267-
c.writer = framer.Writer(rwc)
268-
reader := framer.Reader(rwc)
269-
c.start(ctx, reader, options.Preempter)
270-
return c
271-
}
272-
273213
func (c *Connection) start(ctx context.Context, reader Reader, preempter Preempter) {
274214
c.updateInFlight(func(s *inFlightState) {
275215
select {
276216
case <-c.done:
277-
// Bind already closed the connection; don't start a goroutine to read it.
217+
// The connection was already closed; don't start a goroutine to read it.
278218
return
279219
default:
280220
}
281221

282222
// The goroutine started here will continue until the underlying stream is closed.
283-
//
284-
// (If the Binder closed the Connection already, this should error out and
285-
// return almost immediately.)
286223
s.reading = true
287224
go c.readIncoming(ctx, reader, preempter)
288225
})
@@ -439,18 +376,6 @@ type AsyncCall struct {
439376
// This can be used to cancel the call if needed.
440377
func (ac *AsyncCall) ID() ID { return ac.id }
441378

442-
// IsReady can be used to check if the result is already prepared.
443-
// This is guaranteed to return true on a result for which Await has already
444-
// returned, or a call that failed to send in the first place.
445-
func (ac *AsyncCall) IsReady() bool {
446-
select {
447-
case <-ac.ready:
448-
return true
449-
default:
450-
return false
451-
}
452-
}
453-
454379
// retire processes the response to the call.
455380
//
456381
// It is an error to call retire more than once: retire is guarded by the

internal/jsonrpc2/frame.go

Lines changed: 0 additions & 208 deletions
This file was deleted.

0 commit comments

Comments
 (0)