gRPC server
Table of contents
- Overview
- Turning gRPC on
- Service definition
- Quick start (Python)
- Quick start (grpcurl)
- Generating client stubs
- Frame streaming
- External connections
- Comparison with the TCP/JSON API
Overview
Serial Studio exposes its entire API over gRPC on port 8888. The gRPC server starts automatically when the API server is enabled. Official Serial Studio downloads always include gRPC support; a binary built from source with the default CMake configuration (ENABLE_GRPC=OFF) omits the gRPC controls from Preferences and never opens port 8888. It provides:
- High-performance frame streaming. Binary protobuf encoding is smaller and faster than JSON for the same frame.
- Typed service definition. A full
.protofile for code generation in any language. - Server-streaming RPCs. Real-time frame and raw data push, no polling.
- Cross-language support. Python, C++, Go, Java, Rust, Node.js, C#, and more.
The gRPC server shares the same command set as the TCP/JSON API. Any command available on port 7777 can run over gRPC on port 8888.
Turning gRPC on
The gRPC server starts automatically whenever the API server is enabled:
- Open Preferences (wrench icon or Ctrl/Cmd+,).
- On the General tab, scroll to the API & Plugins section.
- Turn on "Enable API Server (Port 7777)".
- Click OK.
Both the TCP/JSON server (port 7777) and the gRPC server (port 8888) start together.
Service definition
The gRPC API is defined in doc/grpc/serialstudio.proto in the Serial Studio repository (package serialstudio). Generate client stubs from that file:
service SerialStudioAPI {
rpc ExecuteCommand(CommandRequest) returns (CommandResponse);
rpc ExecuteBatch(BatchRequest) returns (BatchResponse);
rpc StreamFrames(StreamRequest) returns (stream FrameBatch);
rpc StreamRawData(StreamRequest) returns (stream RawBatch);
rpc WriteRawData(RawDataRequest) returns (CommandResponse);
rpc ListCommands(google.protobuf.Empty) returns (CommandList);
}
| RPC | Description |
|---|---|
ExecuteCommand |
Execute a single API command and get the result. |
ExecuteBatch |
Execute multiple commands in one request. |
StreamFrames |
Server-streaming RPC that pushes parsed frames in real time. |
StreamRawData |
Server-streaming RPC that pushes raw bytes from the device. |
WriteRawData |
Send raw bytes to the connected device. |
ListCommands |
List all available API commands. |
Quick start (Python)
Install the gRPC Python packages:
pip install grpcio grpcio-tools
Connect and execute commands:
import grpc
import serialstudio_pb2 as pb
import serialstudio_pb2_grpc as rpc
channel = grpc.insecure_channel('localhost:8888')
stub = rpc.SerialStudioAPIStub(channel)
# Execute a command
resp = stub.ExecuteCommand(pb.CommandRequest(
id="1", command="io.getStatus"))
print(resp.result)
# Stream frames in real-time (each message is a FrameBatch)
for batch in stub.StreamFrames(pb.StreamRequest()):
for frame in batch.frames:
print(frame.frame) # protobuf Struct, convertible to dict
Quick start (grpcurl)
grpcurl is a command-line tool for interacting with gRPC servers:
# List available commands
grpcurl -plaintext localhost:8888 serialstudio.SerialStudioAPI/ListCommands
# Execute a command
grpcurl -plaintext -d '{"command":"io.getStatus","id":"1"}' \
localhost:8888 serialstudio.SerialStudioAPI/ExecuteCommand
# Stream frames (Ctrl+C to stop)
grpcurl -plaintext localhost:8888 serialstudio.SerialStudioAPI/StreamFrames
About the "Export Protobuf File" button. The Export… button under Preferences → General → API & Plugins → Export Protobuf File writes an auto-generated typed schema (package
serialstudio.typed, serviceSerialStudioTypedAPI) with one request message and one RPC per registered command. Use it as machine-readable documentation of every command's parameters. The running server implements only the dynamicSerialStudioAPIservice shown above, so generate client stubs from the repo'sdoc/grpc/serialstudio.proto, not from the exported typed file.
Generating client stubs
Download doc/grpc/serialstudio.proto from the Serial Studio repository, then generate stubs for your language:
# Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. serialstudio.proto
# C++
protoc -I. --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin serialstudio.proto
# Go
protoc -I. --go_out=. --go-grpc_out=. serialstudio.proto
# Java
protoc -I. --java_out=. --grpc-java_out=. serialstudio.proto
# C# / .NET
protoc -I. --csharp_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_csharp_plugin serialstudio.proto
Frame streaming
The StreamFrames RPC is the primary way plugins and external tools receive real-time data. The TCP/JSON server also pushes frames (as JSON lines broadcast to every connected client), but gRPC delivers them as compact binary messages on an explicit per-client stream, which holds up better at high frame rates.
# Stream frames with automatic reconnection
import time
def stream_with_retry(stub):
while True:
try:
for batch in stub.StreamFrames(pb.StreamRequest()):
for frame in batch.frames:
process_frame(frame)
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.UNAVAILABLE:
time.sleep(1)
continue
raise
Each stream message is a FrameBatch whose frames field holds one or more FrameData entries. Each FrameData contains:
- frame. The parsed frame as a protobuf
Struct(equivalent to a JSON object). - timestamp_ms. The frame's timestamp in milliseconds.
External connections
The gRPC server follows the same Allow External API Connections setting as the TCP server:
| Setting | TCP/JSON (7777) | gRPC (8888) |
|---|---|---|
| Disabled (default) | 127.0.0.1:7777 |
127.0.0.1:8888 |
| Enabled | 0.0.0.0:7777 |
0.0.0.0:8888 |
Enable external connections under Preferences → General → API & Plugins → Allow External API Connections.
Security note. Enabling external connections exposes the API to your network. Non-loopback clients must then authenticate: send the access token (shown in the API Access Token field next to the external-connections switch) in the
x-serial-studio-tokenrequest metadata. Loopback clients (127.0.0.1/::1) are exempt. The token is the only barrier, so keep it secret and disable external access when it is not needed.
Comparison with the TCP/JSON API
| Feature | TCP/JSON (port 7777) | gRPC (port 8888) |
|---|---|---|
| Encoding | JSON text | Protobuf binary |
| Frame streaming | JSON lines pushed to all clients | Server-push (StreamFrames) |
| Message size | Larger (JSON overhead) | Smaller (binary encoding) |
| Code generation | Manual parsing | Auto-generated stubs |
| Browser support | TCP clients only (no browser access without a bridge) | grpc-web (needs a proxy) |
| Ease of use | nc, curl, any TCP client |
Needs gRPC tooling |
When to use gRPC:
- Plugins that process real-time frame data at high rates.
- Applications where serialization overhead matters.
- Projects that benefit from strongly typed generated clients.
When to use TCP/JSON:
- Quick scripting and debugging (
nc,curl). - Environments without gRPC tooling.
- MCP (Model Context Protocol) integration with AI assistants.
See the API Reference for the full command list. It's shared by both protocols.
Comments