zenrpc is a JSON-RPC 2.0 server library with Service Mapping Description or OpenRPC support.
It's built on top of go generate instead of reflection.
- SMDBox – Swagger-like JSON RPC API browser, compatible with smd scheme, generated by zenrpc.
 - zenrpc middlewares collection
 - brokersrv for using NATS as transport
 - rpcgen – library for generating Go/TypeScript/PHP RPC clients and OpenRPC schema support
 - rpcdiff – diff generator between old and new OpenRPC schemas.
 
Service is struct with RPC methods, service represents RPC namespace.
- Install zenrpc generator: 
go install github.com/vmkteam/zenrpc/v2/zenrpc@latest - Import 
github.com/vmkteam/zenrpc/v2into our code with rpc service. - Add trailing comment 
//zenrpcto your service or embedzenrpc.Serviceinto your service struct. - Write your funcs almost as usual.
 - Do not forget run 
go generateorzenrpcfor magic 
func(Service) Method([args]) (<value>, <error>)
func(Service) Method([args]) <value>
func(Service) Method([args]) <error>
func(Service) Method([args])
- Value could be a pointer
 - Error is error or *zenrpc.Error
 
package main
import (
	"context"
	"errors"
	"flag"
	"log"
	"math"
	"net/http"
	"os"
	"github.com/vmkteam/zenrpc/v2"
	"github.com/vmkteam/zenrpc/v2/testdata"
)
type ArithService struct{ zenrpc.Service }
// Sum sums two digits and returns error with error code as result and IP from context.
func (as ArithService) Sum(ctx context.Context, a, b int) (bool, *zenrpc.Error) {
	r, _ := zenrpc.RequestFromContext(ctx)
	return true, zenrpc.NewStringError(a+b, r.Host)
}
// Multiply multiples two digits and returns result.
func (as ArithService) Multiply(a, b int) int {
	return a * b
}
type Quotient struct {
	Quo, Rem int
}
func (as ArithService) Divide(a, b int) (quo *Quotient, err error) {
	if b == 0 {
		return nil, errors.New("divide by zero")
	} else if b == 1 {
		return nil, zenrpc.NewError(401, errors.New("we do not serve 1"))
	}
	return &Quotient{
		Quo: a / b,
		Rem: a % b,
	}, nil
}
// Pow returns x**y, the base-x exponential of y. If Exp is not set then default value is 2.
//
//zenrpc:exp=2
func (as ArithService) Pow(base float64, exp float64) float64 {
	return math.Pow(base, exp)
}
//go:generate zenrpc
func main() {
	addr := flag.String("addr", "localhost:9999", "listen address")
	flag.Parse()
	rpc := zenrpc.NewServer(zenrpc.Options{ExposeSMD: true})
	rpc.Register("arith", testdata.ArithService{})
	rpc.Register("", testdata.ArithService{}) // public
	rpc.Use(zenrpc.Logger(log.New(os.Stderr, "", log.LstdFlags)))
	http.Handle("/", rpc)
	log.Printf("starting arithsrv on %s", *addr)
	log.Fatal(http.ListenAndServe(*addr, nil))
}All comments are optional.
// Method comments
//
//zenrpc:<method parameter>[=<default value>][whitespaces<description>]
//zenrpc:<error code>[whitespaces<description>]
//zenrpc:return[whitespaces<description>]
 
Struct comments
type MyService struct {} //zenrpc
-  Requests
- Single requests
 - Batch requests
 - Notifications
 
 -  Parameters
- Named
 - Position
 - Default values
 
 -  SMD Schema
- Input
 - Output
 - Codes
 
 
- go generate
 -  Transports
- HTTP
 - WebSocket
 - NATS via brokersrv
 
 -  Server middleware
- Basic support
 - Metrics
 - Logging