@@ -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-
273213func (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.
440377func (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
0 commit comments