smithery/pluginagentmarketplace

go-grpc

Build gRPC services with Go - protobuf, streaming, interceptors

Installation

$ npx skills add smithery/pluginagentmarketplace --skill go-grpc

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/pluginagentmarketplace · top by installs.

npx skills add smithery/pluginagentmarketplace

Browse all from smithery/pluginagentmarketplace

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,107 B
  • docs SUMMARY.md 78 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Go gRPC Skill

Build high-performance gRPC services with Go.

Overview

Complete guide for gRPC development including protobuf design, streaming, interceptors, and error handling.

Parameters

Parameter Type Required Default Description
streaming string no "unary" Type: "unary", "server", "client", "bidi"
auth string no "none" Auth: "none", "jwt", "mtls"

Core Topics

Protobuf Definition

syntax = "proto3";
package api.v1;
option go_package = "github.com/example/api/v1;apiv1";

service UserService {
    rpc GetUser(GetUserRequest) returns (GetUserResponse);
    rpc ListUsers(ListUsersRequest) returns (stream User);
    rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}

message User {
    int64 id = 1;
    string name = 2;
    string email = 3;
    google.protobuf.Timestamp created_at = 4;
}

Server Implementation

type userServer struct {
    apiv1.UnimplementedUserServiceServer
    store UserStore
}

func (s *userServer) GetUser(ctx context.Context, req *apiv1.GetUserRequest) (*apiv1.GetUserResponse, error) {
    user, err := s.store.FindByID(ctx, req.Id)
    if err != nil {
        if errors.Is(err, ErrNotFound) {
            return nil, status.Error(codes.NotFound, "user not found")
        }
        return nil, status.Error(codes.Internal, "internal error")
    }

    return &apiv1.GetUserResponse{
        User: toProtoUser(user),
    }, nil
}

func (s *userServer) ListUsers(req *apiv1.ListUsersRequest, stream apiv1.UserService_ListUsersServer) error {
    users, err := s.store.List(stream.Context(), req.PageSize)
    if err != nil {
        return status.Error(codes.Internal, "failed to list users")
    }

    for _, user := range users {
        if err := stream.Send(toProtoUser(user)); err != nil {
            return err
        }
    }
    return nil
}

Interceptors

func LoggingInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor {
    return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
        start := time.Now()

        resp, err := handler(ctx, req)

        logger.Info("grpc call",
            "method", info.FullMethod,
            "duration", time.Since(start),
            "error", err,
        )

        return resp, err
    }
}

func RecoveryInterceptor() grpc.UnaryServerInterceptor {
    return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
        defer func() {
            if r := recover(); r != nil {
                err = status.Errorf(codes.Internal, "panic: %v", r)
            }
        }()
        return handler(ctx, req)
    }
}

Client with Retry

func NewClient(addr string) (apiv1.UserServiceClient, error) {
    conn, err := grpc.Dial(addr,
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithUnaryInterceptor(
            grpc_retry.UnaryClientInterceptor(
                grpc_retry.WithMax(3),
                grpc_retry.WithBackoff(grpc_retry.BackoffExponential(100*time.Millisecond)),
                grpc_retry.WithCodes(codes.Unavailable, codes.ResourceExhausted),
            ),
        ),
    )
    if err != nil {
        return nil, err
    }

    return apiv1.NewUserServiceClient(conn), nil
}

gRPC Status Codes

Code Use Case
OK Success
INVALID_ARGUMENT Bad input
NOT_FOUND Resource missing
ALREADY_EXISTS Duplicate
DEADLINE_EXCEEDED Timeout
UNAVAILABLE Service down
INTERNAL Server bug

Troubleshooting

Debug Commands

grpcurl -plaintext localhost:50051 list
grpcurl -plaintext -d '{"id": 1}' localhost:50051 api.v1.UserService/GetUser

Usage

Skill("go-grpc")