What Is JSON-RPC-Based Protocol?

A JSON-RPC-based protocol is a lightweight, standardized way for different software systems (like apps, servers, or AI models) to communicate by sending and receiving structured messages in JSON format. The “JSON-RPC” part means the messages follow a specific format (JSON) and structure (RPC, or Remote Procedure Call), ensuring clarity and consistency.

Why JSON-RPC? Plain HTTP or TCP refers to lower-level transport protocols that carry data between systems. While JSON-RPC can (and often does) run over HTTP or WebSocket (which uses TCP), using raw HTTP or TCP without JSON-RPC’s structure would be problematic.

HTTP: HTTP is great for stateless, resource-based APIs (e.g., REST, where you GET /users/123 to fetch data). But it doesn’t natively support function-call semantics like “invoke this specific tool with these parameters.” You’d have to define custom endpoints (e.g., /move-to-position) for every tool, which gets messy for your “all-kinds” server with many tools. TCP: Raw TCP is even lower-level, just a stream of bytes with no inherent structure. You’d need to invent your own message format, parsing logic, and error handling from scratch—recreating what JSON-RPC already provides.

It’s worth noting the three layers:

  • Application Layer (HTTP): Your browser formats a request for the webpage. HTTP (web), WebSocket (real-time), or SMTP (email)
  • Transport Layer (TCP): Breaks the request into packets, ensures they arrive reliably.
  • Network Layer (IP): Routes those packets across the internet to the server.

Robots often use WebSocket for real-time communication because it provides a persistent, bidirectional, low-latency connection over TCP, which is ideal for dynamic, time-sensitive tasks like controlling robotic movements, streaming sensor data, or coordinating actions.

websocket application in robot on server end is like

import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f"Received: {message}")
        await websocket.send(f"Echo: {message}")

async def main():
    server = await websockets.serve(echo, "localhost", 8765)
    print("WebSocket server running on ws://localhost:8765")
    await server.wait_closed()

if __name__ == "__main__":
    asyncio.run(main())

on client end is

import websocket
import time

def on_message(ws, message):
    print(f"Server response: {message}")

def on_error(ws, error):
    print(f"Error: {error}")

def on_close(ws, close_status_code, close_msg):
    print("Connection closed")

def on_open(ws):
    print("Connected to server")
    # Send a test message
    ws.send("Hello, WebSocket!")

if __name__ == "__main__":
    ws = websocket.WebSocketApp("ws://localhost:8765",
                                on_open=on_open,
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close)
    ws.run_forever()

the Anthropic MCP server library typically embeds WebSocket support for JSON-RPC communication, using it as the default transport for real-time, bidirectional interactions.

Communication layers compare:

  • DDS (RTPS) → real-time robotics middleware (UDP/TCP, binary, ultra-low latency)
  • Kafka protocol → distributed, durable messaging (TCP, binary, high-throughput)
  • WebSocket → persistent browser/server channel (TCP, framed messages)
  • HTTP → universal request/response (TCP, text-based, highest overhead)

API Style Comparison: gRPC vs JSON-RPC vs REST

Feature / AspectgRPC 🚀JSON-RPC 🌐REST 🌍
TransportHTTP/2 (binary framing, multiplexed streams)Typically HTTP/1.1 (but transport-agnostic)HTTP/1.1 (standard verbs: GET, POST, PUT…)
EncodingProtocol Buffers (binary, compact)JSON (text, verbose)JSON / XML / YAML (usually JSON today)
Schema / ContractStrongly typed (.proto schema required)No schema (free-form JSON)No enforced schema (can use OpenAPI/Swagger)
Performance🚀 High (small payload, fast parsing)⚡ Medium/Low (JSON overhead)⚡ Medium (JSON overhead, HTTP/1.1 limits)
Streaming✅ Yes (client, server, bidirectional)❌ No (request-response only)❌ No (request-response only)
Ease of UseRequires tooling (codegen, .proto files)Very simple (just JSON messages)Simple (just HTTP + JSON)
Readability❌ Hard (binary messages not human-readable)✅ Easy (plain JSON)✅ Easy (plain JSON or XML)
FeaturesDeadlines, cancellations, load balancing, TLSMinimal, just method/params/results/errorsRich ecosystem: caching, proxies, auth
Error HandlingStatus codes + error messagesJSON error objectsHTTP status codes + JSON/XML error body
Best ForMicroservices, high-throughput APIs, streamingBlockchain APIs, simple RPC-based callsPublic APIs, CRUD services, web integration
ExamplesGoogle Cloud APIs, Kubernetes, IstioEthereum JSON-RPC, Bitcoin RPCTwitter API, GitHub API, RESTful web services
  • Style: Resource-based (everything is a thing you interact with).
  • Transport: Always HTTP.
  • Format: Usually JSON (but can be XML, etc.).
  • How it looks: CRUD

but gRPC

  • Style: Function call based (like JSON-RPC, but more structured).
  • Transport: HTTP/2 (binary protocol).
  • Format: Protocol Buffers (Protobuf), a compact binary format.
  • How it looks (IDL in .proto file):

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.