gRPC Studio is a reflection-based UI for exploring and calling gRPC services. Point the backend at a gRPC server with server reflection enabled, and the frontend discovers services, renders protobuf request forms, invokes unary RPCs over HTTP, and bridges streaming RPCs over WebSocket.
- Reflection discovery for
grpc.reflection.v1andv1alpha - Unary, server-streaming, client-streaming, and bidirectional-streaming RPCs
- Dynamic protobuf forms from
@bufbuild/protobufdescriptors - Nested messages, repeated fields, maps, oneofs, enums, bytes, timestamps, and wrapper types
- TLS and mTLS outbound gRPC connections
- Backend auth plugins for outbound metadata
- Optional Microsoft Entra ID auth for the web UI
- Per-method request history and shareable request links
- Production-grade observability with Prometheus metrics
See the light-mode demo gallery for screenshots and a walkthrough GIF covering service discovery, form/JSON/schema request inputs, response views, share links, request history, and all four RPC modes.
React UI
| POST /api/grpc/discover service + method list
| POST /api/grpc/descriptor-set base64 FileDescriptorSet for a message type
| POST /api/grpc/invoke unary RPC
| WS /ws/grpc streaming RPCs
v
Node/Express backend
| grpc-js-reflection-client list/describe/fetch descriptors
| @bufbuild/protobuf registry, JSON encode/decode, descriptor serialization
| @connectrpc/connect-node outgoing reflected gRPC client calls
v
Target gRPC server with reflection enabled
The backend returns raw descriptor sets, not custom schema JSON. The frontend parses those descriptor sets into Buf DescMessage / DescField objects and renders directly from the descriptor API.
Install dependencies:
npm installRun the default local setup:
npm run devRun the example PetStore service too:
npm run dev:allPoint gRPC Studio at any local gRPC server with reflection enabled:
npm run quickstart -- 50051Or pass an explicit host and port:
npm run quickstart -- localhost:50051This starts the frontend on http://localhost:3000 and the backend on http://localhost:3001, with the backend targeting the reflected gRPC service you provided.
Start only the backend with the checked-in config:
cd backend
GRPC_STUDIO_CONFIG=../config/backend.yaml npm startStart only the frontend:
cd frontend
npm run devBy default the frontend runs on http://localhost:3000 and the backend on http://localhost:3001.
Backend config is YAML-driven. Set GRPC_STUDIO_CONFIG to the backend YAML file when starting the backend.
client:
mode: plaintext # plaintext | tls | mtls
target:
host: localhost
port: 50051
auth:
plugins: {}
observability:
enabled: true
metrics:
enabled: true
path: /metrics
includeSystemMetrics: trueFrontend config lives in frontend/public/config/frontend.yaml at runtime, or config/frontend.yaml for repo examples:
api:
baseUrl: "http://localhost:3001"
auth:
enabled: falseChecked-in example configs live under config/, including the default plaintext backend config, a TLS backend example, an mTLS example, and observability examples.
npm run build:shared
cd backend && npm run typecheck
cd frontend && npm run build
cd frontend && npm run test:runThe shared package owns API contract types used by both frontend and backend.
backend/ Express API, reflection discovery, dynamic invocation, WebSocket streams
frontend/ React UI, descriptor cache, schema renderer, method explorer
shared/ Shared HTTP/WebSocket contract types
example/ Reflection-enabled PetStore gRPC test server
config/ Example backend/frontend YAML configs
The backend exposes Prometheus metrics at /metrics.
Key Metrics:
- HTTP request rate, latency, and errors (RED method)
- gRPC invocation rate, latency, and active streams
- WebSocket connection counts and durations
- Cache hit/miss rates
- Node.js process metrics (CPU, memory, event loop)
Prometheus Scrape Example:
scrape_configs:
- job_name: 'grpc-studio'
static_configs:
- targets: ['localhost:3001']
metrics_path: '/metrics'
scrape_interval: 15sSee OBSERVABILITY.md for complete documentation.
- The target server must support gRPC reflection.
- Protobuf descriptors are resolved transitively from reflection and cached by TTL.
- Streaming calls are controlled with JSON WebSocket messages and encoded to real gRPC messages on the backend.
- mTLS certificate status is surfaced in the UI when mTLS is configured.
Pre-built Docker images are available on GitHub Container Registry:
# Pull images
docker pull ghcr.io/electronicarts/grpc-studio/backend:latest
docker pull ghcr.io/electronicarts/grpc-studio/frontend:latest
# Run with docker-compose
docker-compose up -dSee docker/README.md for complete deployment documentation including Kubernetes manifests.
A Helm chart is published to GitHub Container Registry for Kubernetes deployments:
helm upgrade --install my-grpc-studio oci://ghcr.io/electronicarts/helm-charts/grpc-studio \
--set connection.target.host=my-grpc-server.default.svc.cluster.local \
--set connection.target.port=50051 \
--set connection.mode=insecure \
--namespace grpc-studio --create-namespaceSee helm/README.md for configuration options and helm/examples/ for ingress-nginx and Istio setups.
This project uses GitHub Actions for continuous integration and Docker image publishing:
-
CI Pipeline (
.github/workflows/ci.yml): Runs on every push and pull request- Install dependencies
- Copyright header checks
- TypeScript type checking
- ESLint for frontend and backend
- Build frontend and backend
- Run all tests
-
Docker Publish (
.github/workflows/docker-publish.yml): Runs on push to main and tags- Builds multi-architecture images (AMD64, ARM64)
- Publishes to GitHub Container Registry
- Creates GitHub releases for version tags
Before you can contribute, EA must have a Contributor License Agreement (CLA) on file that has been signed by each contributor. You can sign here.