Skip to main content

grpc-server-kit

Batteries-optional async gRPC server toolkit (app facade, builder, TLS, lifecycle, health, interceptors, observability)

PyPI Python License CI codecov Docs

grpc-server-kit gives you a clean, production-grade foundation for building grpc.aio servers: a one-object GrpcApp facade, validated channel options, TLS/mTLS credential loading, graceful signal-driven shutdown, streaming-aware interceptors, and gRPC health checking — with optional extras for reflection, channelz, Prometheus metrics, OpenTelemetry tracing, Sentry, Dishka DI, and typed pydantic settings.

The core depends only on grpcio. Every integration is an opt-in extra, so you install exactly what you use.

Installation

pip install grpc-server-kit                      # core (grpcio only)
pip install "grpc-server-kit[settings]"          # + pydantic settings models
pip install "grpc-server-kit[health]"            # + gRPC health checking
pip install "grpc-server-kit[metrics,tracing]"   # + Prometheus + OpenTelemetry
pip install "grpc-server-kit[all]"               # everything

Requirements: Python 3.12+

Quick start

import asyncio

from grpc_server_kit import GrpcApp

app = GrpcApp(port=50051)
app.add_servicer(MyServicer(), add_MyServiceServicer_to_server)

asyncio.run(app.run())   # build + bind + SIGINT/SIGTERM + graceful shutdown

That's the whole server. GrpcApp builds the grpc.aio server, binds the port (TLS-aware), installs signal handlers, and serves until termination. More knobs when you need them:

from grpc_server_kit import GrpcApp, GrpcServerConfig
from grpc_server_kit.aio.interceptors import (
    AsyncContextInterceptor, AsyncExceptionHandlerInterceptor,
    AsyncMetricsInterceptor, AsyncRequestLoggerInterceptor, HeaderConfig,
)
from grpc_server_kit.observability.metrics import get_grpc_server_metrics

config = GrpcServerConfig(host="[::]", port=50051, grace_period=10.0)   # stdlib dataclass
app = GrpcApp(config, interceptors=[
    AsyncMetricsInterceptor(metrics=get_grpc_server_metrics(), service_name="my.pkg.MyService"),
    AsyncContextInterceptor([HeaderConfig("x-request-id", "request_id")]),
    AsyncRequestLoggerInterceptor(),
    AsyncExceptionHandlerInterceptor(MY_ERROR_STATUS_MAP),   # domain error → gRPC status
])
app.add_servicer(MyServicer(), add_MyServiceServicer_to_server)
app.enable_health(checkers=[DatabaseHealthChecker(session_maker)])   # [health] extra
app.enable_reflection(["my.pkg.MyService"])                          # [reflection] extra

asyncio.run(app.run())

Prefer pydantic-validated, env-friendly settings? Use grpc_server_kit.settings.BaseGrpcServerSettings (the [settings] extra) — GrpcServerConfig and BaseGrpcServerSettings are interchangeable everywhere the kit accepts settings.

Streaming-aware interceptors

Every interceptor wraps the whole RPC for all four call kinds — unary-unary, unary-stream, stream-unary, stream-stream. Durations cover the full stream, errors raised mid-stream are mapped to proper gRPC statuses, and cleanup always runs. Write your own by implementing a single async-generator hook:

from grpc_server_kit.aio.interceptors import AsyncServerInterceptor, RpcCall

class TimingInterceptor(AsyncServerInterceptor):
    async def around_call(self, call: RpcCall):
        start = time.perf_counter()
        try:
            yield                      # the RPC (or the full response stream) runs here
        finally:
            log.info("%s took %.3fs", call.method_name, time.perf_counter() - start)

Canonical chain order (outermost first): metrics → context → logger → tracing → exception handler → sentry. The exception handler maps exception types to gRPC statuses over the MRO and sends safe, non-leaking details; deliberate context.abort() calls pass through untouched. Sentry sits inside the exception handler so it observes raw handler exceptions before they become aborts (outside it would never capture anything), with a capture filter that reports only server-class errors.

Advanced API

GrpcApp is sugar over small, composable pieces you can use directly — for DI containers, custom lifecycles, or embedding:

from grpc_server_kit import bind_server_port
from grpc_server_kit.aio import AsyncGrpcServerBuilder, run_async_grpc_server

server = (
    AsyncGrpcServerBuilder(settings)
    .with_interceptors(interceptors)
    .with_servicers(lambda s: add_MyServiceServicer_to_server(MyServicer(), s))
    .with_reflection(["my.pkg.MyService"])
    .build()
)
bind_server_port(server, settings)            # honors settings.ssl_enabled (TLS/mTLS)
await run_async_grpc_server(server, address=f"{settings.host}:{settings.port}")

Dishka DI providers (cut the per-service boilerplate)

If your service uses Dishka, the kit ships ready-made providers so you register a handful of providers instead of hand-writing the interceptor list, settings aliasing, and a metrics provider. grpc_server_providers(...) bundles the standard set in one call:

from dishka import make_async_container
from grpc_server_kit.dishka import GrpcioProvider, FromDishka, inject
from grpc_server_kit.aio.dishka import grpc_server_providers
from grpc_server_kit.aio.server import AsyncServer
from grpc_server_kit.aio import run_async_grpc_server
from grpc_server_kit import bind_server_port

container = make_async_container(
    *grpc_server_providers(                       # settings + metrics + sentry/tracer seams
        settings.grpc,                            # + the canonical interceptor chain + AsyncServer
        service_name="my.pkg.MyService",
        error_status_map=MY_ERROR_STATUS_MAP,     # service-specific domain map (optional)
        metrics_enabled=settings.grpc.metrics_enabled,
    ),
    GrpcioProvider(),                             # request-scoped ServicerContext for FromDishka
    MyDomainProvider(),                           # your use-cases / repos
)

server = await container.get(AsyncServer)         # interceptors + options already wired
add_MyServiceServicer_to_server(MyServicer(), server)   # AsyncServer works directly
bind_server_port(server, settings.grpc)
await run_async_grpc_server(server, address=f"{settings.grpc.host}:{settings.grpc.port}")

The interceptor chain is built in the canonical order (metrics → context → logger → tracing → exception → sentry → DishkaAioInterceptor), with include_* toggles and extra_outer / extra_inner slots on GrpcServerInterceptorsProvider. Providers degrade gracefully: the metrics / Sentry / tracer seams resolve to None when disabled or their extra is absent, and the interceptors no-op. SDK initialization (sentry_sdk.init, OpenTelemetry setup, the /metrics HTTP server) is a process-wide concern and is not done by these providers. Requires [dishka] (+ [metrics]/[sentry]/[tracing] for those seams).

Granular providers (GrpcServerSettingsProvider, PrometheusGrpcServerMetricsProvider, SentryAdapterProvider, TracerAdapterProvider, GrpcServerInterceptorsProvider, AsyncGrpcServerProvider) are available for finer control.

What's inside

Layout convention: all async code lives under a single grpc_server_kit.aio package (mirroring grpc.aio), organized by domain (aio.health, aio.interceptors, aio.observability, aio.dishka). Modules that work for both sync and async stay at the top level — either directly (config, options, credentials, server, protocols, signals, settings) or as shared domain packages (interceptors → constants/utils, observability → protocols/metrics/sentry, dishka → providers).

Module Responsibility Extra
aio.GrpcApp One-object facade: config → servicers → run core
config.GrpcServerConfig Zero-dependency settings dataclass core
aio.builder.AsyncGrpcServerBuilder Fluent builder for an AsyncServer core
aio.create_async_grpc_server / aio.AsyncServer Server factory + typed wrapper core
aio.ServerLifecycleManager / aio.run_async_grpc_server Start/serve/stop with graceful shutdown core
aio.interceptors.* streaming-aware base + context, logger, metrics, tracing, sentry, exception-handler core
options / credentials / server / signals / protocols Channel options, TLS/mTLS, port binding, SIGINT/SIGTERM, seams core
settings.BaseGrpcServerSettings Pydantic config model settings
aio.health.* gRPC Health v1 servicer, orchestrator, TTL cache, pg/redis checkers health
observability.metrics.GrpcServerMetrics Prometheus metric definitions metrics
aio.observability.tracing.instrument_aio_server OpenTelemetry instrumentation tracing
observability.sentry.SentrySdkAdapter Sentry adapter for the sentry interceptor sentry
aio.dishka.* / dishka.* DI providers + DishkaAioInterceptor re-export dishka

Optional dependencies

Extra Pulls in Enables
reflection grpcio-reflection server reflection
channelz grpcio-channelz channelz debugging
settings pydantic BaseGrpcServerSettings / BaseHealthSettings
health grpcio-health-checking health servicer / orchestrator / cache
postgres sqlalchemy[asyncio] DatabaseHealthChecker
redis redis RedisHealthChecker
metrics prometheus-client GrpcServerMetrics
tracing opentelemetry-instrumentation-grpc instrument_aio_server
sentry sentry-sdk SentrySdkAdapter
dishka dishka, protobuf DI providers + DishkaAioInterceptor
all all of the above everything

Examples

Runnable, self-contained scripts in examples/ — each prints what it's doing and exits on its own:

  • minimal_server.py — the smallest real server: GrpcApp, one servicer, asyncio.run(app.run()).
  • observability_chain.py — the canonical interceptor chain (metrics → context → logger → tracing → exception handler → sentry) wired by hand.
  • custom_interceptor.py — writing your own streaming-aware interceptor with AsyncServerInterceptor.around_call.
  • health_checks.py — app.enable_health() with a custom dependency checker, driven through the real grpc_health.v1 stubs.

Documentation

Full documentation at bedrock-python.github.io/grpc-server-kit.

  • For AI agents — the whole API surface, the rules that break a server when broken and a map of the rest, on one page to hand to a coding assistant

License

Apache 2.0 — see LICENSE.

Metadata

Release files for grpc-server-kit 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grpc-server-kit 0.2.0
File Size Uploaded
grpc_server_kit-0.2.0.tar.gz 61.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for grpc-server-kit 0.2.0
File Interpreter ABI Platform
grpc_server_kit-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 147.3 kB

Release files / grpc_server_kit-0.2.0.tar.gz

Download URL grpc_server_kit-0.2.0.tar.gz
Size 61.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c723dfcc7b0b09635ffbfd0dd2e585f12899a251e17ed7b3131fc6d736038657
BLAKE2b-256 checksum
How to use checksums
7f8844d5dc8cfd75878162ddf0500194e46ad28d70d67da78a11527267d35806
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / grpc_server_kit-0.2.0-py3-none-any.whl

Download URL grpc_server_kit-0.2.0-py3-none-any.whl
Size 86.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6e862547670a5ca491ceb0441339b719d802621b262b97cda261112275eb9a7
BLAKE2b-256 checksum
How to use checksums
2efd8092d68ce259da08fca34553295ce9d921ba51658876f8f2d01380d6cd48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page