TLDR: you simply need to provide the class value.
The struct form defines accessors, setters, predicate, constructor, etc. Therefore, you need to provide them all if you want your client to have a full capability to manipulate structs:
(struct foo (bar) #:mutable)
;; this defines
;; constructor: foo
;; accessors: foo-bar
;; setters: set-foo-bar!
;; predicate: foo?
The class form, on the other hand, returns a first-class class value, and does not define anything at all. The class value then can be utilized by using forms such as new and send (which is provided by #lang racket already).
(class object% (super-new))
;; this defines nothing, but results in a class value
So it suffices to just provide an identifier bound to this class value. Here's an example:
;; lib.rkt
#lang racket
(define human%
(class object% (super-new)
(define/public (speak)
(displayln "hello world!"))))
(provide human%)
;; client.rkt
#lang racket
(require "lib.rkt")
(send (new human%) speak)
;; display hello world!