Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    pluginagentmarketplace

    communication-protocols

    pluginagentmarketplace/communication-protocols
    Coding
    2

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Game server communication protocols including gRPC, REST, and custom binary protocols

    SKILL.md

    Communication Protocols for Game Servers

    Implement efficient communication protocols between game services and clients.

    Protocol Selection Guide

    Protocol Latency Throughput Use Case
    Custom Binary Lowest Highest Real-time gameplay
    gRPC Low High Service-to-service
    WebSocket Low Medium Browser clients
    REST Medium Medium Admin APIs, lobbies
    QUIC Low High Mobile, unreliable networks

    gRPC for Game Services

    // matchmaking.proto
    syntax = "proto3";
    
    package game.matchmaking;
    
    service Matchmaking {
        rpc FindMatch(MatchRequest) returns (MatchResponse);
        rpc JoinQueue(QueueRequest) returns (stream QueueUpdate);
        rpc CancelQueue(CancelRequest) returns (CancelResponse);
    }
    
    message MatchRequest {
        string player_id = 1;
        string game_mode = 2;
        int32 skill_rating = 3;
        repeated string preferred_regions = 4;
    }
    
    message MatchResponse {
        string match_id = 1;
        string server_address = 2;
        int32 server_port = 3;
        repeated TeamAssignment teams = 4;
        string connection_token = 5;
    }
    
    message QueueUpdate {
        enum Status {
            SEARCHING = 0;
            MATCH_FOUND = 1;
            CANCELLED = 2;
        }
        Status status = 1;
        int32 estimated_wait_seconds = 2;
        int32 players_in_queue = 3;
    }
    

    Go gRPC Server

    type matchmakingServer struct {
        pb.UnimplementedMatchmakingServer
        matchmaker *Matchmaker
    }
    
    func (s *matchmakingServer) FindMatch(
        ctx context.Context,
        req *pb.MatchRequest,
    ) (*pb.MatchResponse, error) {
        match, err := s.matchmaker.FindMatch(ctx, req.PlayerId, req.GameMode, req.SkillRating)
        if err != nil {
            return nil, status.Errorf(codes.Internal, "matchmaking failed: %v", err)
        }
    
        return &pb.MatchResponse{
            MatchId:       match.ID,
            ServerAddress: match.ServerAddr,
            ServerPort:    int32(match.ServerPort),
            ConnectionToken: match.Token,
        }, nil
    }
    
    func (s *matchmakingServer) JoinQueue(
        req *pb.QueueRequest,
        stream pb.Matchmaking_JoinQueueServer,
    ) error {
        updates := s.matchmaker.Subscribe(req.PlayerId)
        defer s.matchmaker.Unsubscribe(req.PlayerId)
    
        for update := range updates {
            if err := stream.Send(update); err != nil {
                return err
            }
            if update.Status == pb.QueueUpdate_MATCH_FOUND {
                return nil
            }
        }
        return nil
    }
    

    Custom Binary Protocol

    // Packet header (8 bytes)
    struct PacketHeader {
        uint8_t type;        // Message type
        uint8_t flags;       // Compression, reliability flags
        uint16_t length;     // Payload length
        uint32_t sequence;   // Packet sequence for ordering/ack
    };
    
    enum PacketType : uint8_t {
        PLAYER_INPUT    = 0x01,
        STATE_UPDATE    = 0x02,
        PLAYER_JOIN     = 0x03,
        PLAYER_LEAVE    = 0x04,
        CHAT_MESSAGE    = 0x10,
        PING            = 0xFE,
        PONG            = 0xFF
    };
    
    enum PacketFlags : uint8_t {
        FLAG_RELIABLE   = 0x01,
        FLAG_COMPRESSED = 0x02,
        FLAG_ENCRYPTED  = 0x04
    };
    
    // Zero-copy packet builder
    class PacketBuilder {
        uint8_t buffer[MAX_PACKET_SIZE];
        size_t offset = sizeof(PacketHeader);
    
    public:
        PacketBuilder& writeU8(uint8_t v) {
            buffer[offset++] = v;
            return *this;
        }
    
        PacketBuilder& writeU16(uint16_t v) {
            *reinterpret_cast<uint16_t*>(&buffer[offset]) = htons(v);
            offset += 2;
            return *this;
        }
    
        PacketBuilder& writeFloat(float v) {
            *reinterpret_cast<float*>(&buffer[offset]) = v;
            offset += 4;
            return *this;
        }
    
        std::span<uint8_t> build(PacketType type, uint8_t flags = 0) {
            auto* header = reinterpret_cast<PacketHeader*>(buffer);
            header->type = static_cast<uint8_t>(type);
            header->flags = flags;
            header->length = htons(offset - sizeof(PacketHeader));
            header->sequence = htonl(nextSequence++);
            return {buffer, offset};
        }
    };
    
    // Player input packet (compact)
    struct PlayerInputPacket {
        uint32_t tick;          // 4 bytes
        uint8_t keys;           // 1 byte: WASD + jump + fire (bitfield)
        int16_t aim_x;          // 2 bytes: quantized aim [-32768, 32767]
        int16_t aim_y;          // 2 bytes: quantized aim
    };  // Total: 9 bytes
    

    WebSocket for Browser Games

    // Server (Node.js with ws)
    const WebSocket = require('ws');
    
    const wss = new WebSocket.Server({
        port: 8080,
        perMessageDeflate: true,  // Compression
        maxPayload: 64 * 1024     // 64KB limit
    });
    
    wss.on('connection', (ws, req) => {
        const playerId = authenticate(req);
    
        ws.on('message', (data, isBinary) => {
            if (isBinary) {
                // Binary protocol for gameplay
                const view = new DataView(data.buffer);
                const type = view.getUint8(0);
                handleBinaryMessage(playerId, type, view);
            } else {
                // JSON for lobby/chat
                const msg = JSON.parse(data);
                handleJsonMessage(playerId, msg);
            }
        });
    
        ws.on('close', () => {
            onPlayerDisconnect(playerId);
        });
    
        // Send binary state updates at 60Hz
        const tickInterval = setInterval(() => {
            if (ws.readyState === WebSocket.OPEN) {
                const state = serializeGameState(playerId);
                ws.send(state, { binary: true });
            }
        }, 16);
    
        ws.on('close', () => clearInterval(tickInterval));
    });
    
    // Client
    class GameClient {
        constructor(url) {
            this.ws = new WebSocket(url);
            this.ws.binaryType = 'arraybuffer';
    
            this.ws.onmessage = (event) => {
                if (event.data instanceof ArrayBuffer) {
                    this.handleStateUpdate(new DataView(event.data));
                } else {
                    this.handleJsonMessage(JSON.parse(event.data));
                }
            };
        }
    
        sendInput(keys, aimX, aimY) {
            const buffer = new ArrayBuffer(9);
            const view = new DataView(buffer);
            view.setUint32(0, this.currentTick);
            view.setUint8(4, keys);
            view.setInt16(5, aimX);
            view.setInt16(7, aimY);
            this.ws.send(buffer);
        }
    }
    

    REST API for Game Services

    // Lobby API with proper error handling
    type LobbyHandler struct {
        lobbyService *LobbyService
    }
    
    func (h *LobbyHandler) CreateLobby(w http.ResponseWriter, r *http.Request) {
        var req CreateLobbyRequest
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            respondError(w, http.StatusBadRequest, "invalid request body")
            return
        }
    
        lobby, err := h.lobbyService.Create(r.Context(), req)
        if err != nil {
            switch {
            case errors.Is(err, ErrPlayerAlreadyInLobby):
                respondError(w, http.StatusConflict, err.Error())
            case errors.Is(err, ErrMaxLobbiesReached):
                respondError(w, http.StatusTooManyRequests, err.Error())
            default:
                respondError(w, http.StatusInternalServerError, "internal error")
            }
            return
        }
    
        respondJSON(w, http.StatusCreated, lobby)
    }
    
    func respondJSON(w http.ResponseWriter, status int, data interface{}) {
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(status)
        json.NewEncoder(w).Encode(data)
    }
    

    Protocol Selection Matrix

    Scenario Protocol Reason
    Real-time gameplay Custom UDP binary Lowest latency
    Microservices gRPC Type safety, streaming
    Web/mobile lobby WebSocket JSON Browser compatibility
    Admin dashboard REST Standard tooling
    Streaming updates gRPC streaming Backpressure handling

    Troubleshooting

    Common Failure Modes

    Error Root Cause Solution
    Connection reset Message too large Chunk large messages
    Timeout Slow processing Async handlers
    Parse error Version mismatch Protocol versioning
    High latency No compression Enable compression

    Debug Checklist

    # gRPC debugging
    GRPC_VERBOSITY=DEBUG GRPC_TRACE=all ./game-server
    
    # WebSocket inspection
    wscat -c ws://localhost:8080
    
    # Protocol buffer decoding
    protoc --decode=game.StateUpdate game.proto < message.bin
    
    # Network trace
    tcpdump -i any port 8080 -w capture.pcap
    

    Unit Test Template

    func TestMatchmakingRPC(t *testing.T) {
        server := setupTestServer()
        defer server.Stop()
    
        conn, err := grpc.Dial(server.Addr, grpc.WithInsecure())
        require.NoError(t, err)
        defer conn.Close()
    
        client := pb.NewMatchmakingClient(conn)
    
        resp, err := client.FindMatch(context.Background(), &pb.MatchRequest{
            PlayerId:    "player123",
            GameMode:    "ranked",
            SkillRating: 1500,
        })
    
        require.NoError(t, err)
        assert.NotEmpty(t, resp.MatchId)
        assert.NotEmpty(t, resp.ServerAddress)
    }
    
    func TestBinaryProtocol(t *testing.T) {
        builder := NewPacketBuilder()
        packet := builder.
            WriteU32(12345).  // tick
            WriteU8(0x0F).    // keys
            WriteI16(1000).   // aim_x
            WriteI16(-500).   // aim_y
            Build(PLAYER_INPUT)
    
        parsed := ParsePlayerInput(packet)
        assert.Equal(t, uint32(12345), parsed.Tick)
        assert.Equal(t, uint8(0x0F), parsed.Keys)
    }
    

    Resources

    • assets/ - Protocol templates
    • references/ - Performance benchmarks
    Recommended Servers
    Discord
    Discord
    Confluence
    Confluence
    Unicorn or Bust
    Unicorn or Bust
    Repository
    pluginagentmarketplace/custom-plugin-server-side-game-dev
    Files