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 }