internal/mcp: rename LocalTransport->InMemoryTransport, and document
Update the design to mention our in-memory transport, since it is generally useful, and update the implementation to use distinct types for InMemoryTransport and StdIOTransport (the fact that they are both implemented as an io.ReadWriteCloser is an implementation detail). Change-Id: I8228ccf2092a56a730c113c4db105fb492cce112 Reviewed-on: https://go-review.googlesource.com/c/tools/+/672715 Reviewed-by: Sam Thanawalla <samthanawalla@google.com> Commit-Queue: Robert Findley <rfindley@google.com> Reviewed-by: Jonathan Amsterdam <jba@google.com> TryBot-Bypass: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
ac828d5a82
commit
dbf57af24b
4 changed files with 33 additions and 13 deletions
|
|
@ -283,6 +283,14 @@ func NewStreamableClientTransport(url string) *StreamableClientTransport {
|
|||
func (*StreamableClientTransport) Connect(context.Context) (Stream, error)
|
||||
```
|
||||
|
||||
Finally, we also provide an in-memory transport, for scenarios such as testing,
|
||||
where the MCP client and server are in the same process.
|
||||
|
||||
```go
|
||||
type InMemoryTransport struct { /* ... */ }
|
||||
func NewInMemoryTransport() (*InMemoryTransport, *InMemoryTransport)
|
||||
```
|
||||
|
||||
**Differences from mcp-go**: The Go team has a battle-tested JSON-RPC
|
||||
implementation that we use for gopls, our Go LSP server. We are using the new
|
||||
version of this library as part of our MCP SDK. It handles all JSON-RPC 2.0
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func sayHi(ctx context.Context, cc *ServerSession, v hiParams) ([]*Content, erro
|
|||
|
||||
func TestEndToEnd(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ct, st := NewLocalTransport()
|
||||
ct, st := NewInMemoryTransport()
|
||||
|
||||
s := NewServer("testServer", "v1.0.0", nil)
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ func basicConnection(t *testing.T, tools ...*ServerTool) (*ServerSession, *Clien
|
|||
t.Helper()
|
||||
|
||||
ctx := context.Background()
|
||||
ct, st := NewLocalTransport()
|
||||
ct, st := NewInMemoryTransport()
|
||||
|
||||
s := NewServer("testServer", "v1.0.0", nil)
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ func TestServerClosing(t *testing.T) {
|
|||
|
||||
func TestBatching(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ct, st := NewLocalTransport()
|
||||
ct, st := NewInMemoryTransport()
|
||||
|
||||
s := NewServer("testServer", "v1.0.0", nil)
|
||||
_, err := s.Connect(ctx, st, nil)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func SayHi(ctx context.Context, cc *mcp.ServerSession, params *SayHiParams) ([]*
|
|||
|
||||
func ExampleServer() {
|
||||
ctx := context.Background()
|
||||
clientTransport, serverTransport := mcp.NewLocalTransport()
|
||||
clientTransport, serverTransport := mcp.NewInMemoryTransport()
|
||||
|
||||
server := mcp.NewServer("greeter", "v0.0.1", nil)
|
||||
server.AddTools(mcp.NewTool("greet", "say hi", SayHi))
|
||||
|
|
|
|||
|
|
@ -48,27 +48,39 @@ type ConnectionOptions struct {
|
|||
Logger io.Writer // if set, write RPC logs
|
||||
}
|
||||
|
||||
// An IOTransport is a [Transport] that communicates using newline-delimited
|
||||
// A StdIOTransport is a [Transport] that communicates over stdin/stdout using
|
||||
// newline-delimited JSON.
|
||||
type StdIOTransport struct {
|
||||
ioTransport
|
||||
}
|
||||
|
||||
// An ioTransport is a [Transport] that communicates using newline-delimited
|
||||
// JSON over an io.ReadWriteCloser.
|
||||
type IOTransport struct {
|
||||
type ioTransport struct {
|
||||
rwc io.ReadWriteCloser
|
||||
}
|
||||
|
||||
func (t *IOTransport) Connect(context.Context) (Stream, error) {
|
||||
func (t *ioTransport) Connect(context.Context) (Stream, error) {
|
||||
return newIOStream(t.rwc), nil
|
||||
}
|
||||
|
||||
// NewStdIOTransport constructs a transport that communicates over
|
||||
// stdin/stdout.
|
||||
func NewStdIOTransport() *IOTransport {
|
||||
return &IOTransport{rwc{os.Stdin, os.Stdout}}
|
||||
func NewStdIOTransport() *StdIOTransport {
|
||||
return &StdIOTransport{ioTransport{rwc{os.Stdin, os.Stdout}}}
|
||||
}
|
||||
|
||||
// NewLocalTransport returns two in-memory transports that connect to
|
||||
// each other, for testing purposes.
|
||||
func NewLocalTransport() (*IOTransport, *IOTransport) {
|
||||
// An InMemoryTransport is a [Transport] that communicates over an in-memory
|
||||
// network connection, using newline-delimited JSON.
|
||||
type InMemoryTransport struct {
|
||||
ioTransport
|
||||
}
|
||||
|
||||
// NewInMemoryTransport returns two InMemoryTransports that connect to each
|
||||
// other.
|
||||
func NewInMemoryTransport() (*InMemoryTransport, *InMemoryTransport) {
|
||||
c1, c2 := net.Pipe()
|
||||
return &IOTransport{c1}, &IOTransport{c2}
|
||||
return &InMemoryTransport{ioTransport{c1}}, &InMemoryTransport{ioTransport{c2}}
|
||||
}
|
||||
|
||||
// handler is an unexported version of jsonrpc2.Handler.
|
||||
|
|
|
|||
Loading…
Reference in a new issue