100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
)
|
|
|
|
// fakeTransport is a scripted Transport for tests. It records starts, closes and
|
|
// the methods it was asked to call so assertions can verify the client's usage.
|
|
type fakeTransport struct {
|
|
startErr error
|
|
closeErr error
|
|
initErr error
|
|
listErr error
|
|
callErr error
|
|
tools []ToolInfo
|
|
|
|
mu sync.Mutex
|
|
starts int
|
|
closes int
|
|
methods []string
|
|
}
|
|
|
|
// Start records a start.
|
|
func (f *fakeTransport) Start(_ context.Context) error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.starts++
|
|
return f.startErr
|
|
}
|
|
|
|
// Call answers the three MCP methods the client issues.
|
|
func (f *fakeTransport) Call(_ context.Context, method string, _ any, result any) error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.methods = append(f.methods, method)
|
|
switch method {
|
|
case "initialize":
|
|
if f.initErr != nil {
|
|
return f.initErr
|
|
}
|
|
if r, ok := result.(*initializeResult); ok {
|
|
r.ServerInfo = serverInfo{Name: "fake-server", Version: "1.0"}
|
|
r.ProtocolVersion = protocolVersion
|
|
}
|
|
case "tools/list":
|
|
if f.listErr != nil {
|
|
return f.listErr
|
|
}
|
|
if r, ok := result.(*listToolsResult); ok {
|
|
for _, t := range f.tools {
|
|
r.Tools = append(r.Tools, toolSpec{Name: t.Name, Description: t.Description, InputSchema: t.InputSchema})
|
|
}
|
|
}
|
|
case "tools/call":
|
|
if f.callErr != nil {
|
|
return f.callErr
|
|
}
|
|
if r, ok := result.(*callToolResult); ok {
|
|
r.Content = []contentBlock{{Type: "text", Text: "hello"}}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// notify records a notification method.
|
|
func (f *fakeTransport) notify(_ context.Context, method string, _ any) error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.methods = append(f.methods, "notify:"+method)
|
|
return nil
|
|
}
|
|
|
|
// Close records a close.
|
|
func (f *fakeTransport) Close() error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.closes++
|
|
return f.closeErr
|
|
}
|
|
|
|
// calledMethods returns a snapshot of the recorded methods.
|
|
func (f *fakeTransport) calledMethods() []string {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
out := make([]string, len(f.methods))
|
|
copy(out, f.methods)
|
|
return out
|
|
}
|
|
|
|
// hasMethod reports whether method was recorded.
|
|
func (f *fakeTransport) hasMethod(method string) bool {
|
|
for _, m := range f.calledMethods() {
|
|
if m == method {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|