The one-person framework for Kubernetes microservices.
gRPC, observability, auth, and an LLM tool surface — wired from a single tonin.toml.
Built for developers who are also their own ops team.
tonin is an opinionated Rust framework for teams that don't have a platform team.
It gives you the whole path from .proto to a deployed, observable, mesh-ready
service — without the week of YAML, Dockerfiles, OTel wiring, and MCP plumbing that
usually stands between an idea and a running endpoint.
The philosophy is sane defaults with a pluggable architecture: every batteries-included
default works on day one, and every capability — cache, database, event bus, config —
swaps to another backend with a single line in tonin.toml. No handler rewrite, no lock-in.
If you're a solo developer or a small team, your scarcest resource is you. tonin is built around that constraint:
- One
.protoin, a deployable service out. The contract is the only thing you have to design. Everything downstream — server boilerplate, container, manifests, telemetry — is generated from it. - No platform tax. The infrastructure decisions a 50-person org pays an SRE team to make (how to wire tracing, where mTLS lives, how the HPA scales) ship as defaults you can override, not blank files you have to fill in.
- Swap, don't rewrite. Capabilities are interfaces. Redis today, something else tomorrow is a TOML change and a dependency flip — your handlers never know.
- AI-native by default. Every gRPC method is automatically a callable MCP tool, so your service is usable by an LLM agent the moment it's usable by a client.
For those counting — the commands to get a running, instrumented, MCP-enabled gRPC service are:
curl -sSfL https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.sh | bashtonin service new greetercd greeter && cargo runThat's it. A gRPC server on :50051, an MCP server on :50052 exposing every RPC as a
tool, OTLP traces flowing to your collector, and Helm charts rendered for your mesh —
none of which you wrote.
tonin ships the core building blocks of a distributed system as first-class, swappable
capabilities. Each works out of the box and is selected or reconfigured in tonin.toml.
- gRPC Transport — tonic/tower server wiring, graceful shutdown, and a generated
typed client, all from your
.proto. You implement one trait; the Router, layers, and bind are handled. - MCP Tool Surface — annotate a handler with
#[mcp_expose]and every gRPC method becomes a JSON-schema'd, LLM-callable tool served by a co-located MCP sidecar. No separate MCP server to maintain. - Telemetry — zero-config OpenTelemetry. OTLP traces and structured logs with W3C
trace-context propagated across service calls, configured from
OTEL_*env vars. - Authentication — bearer extraction, JWT validation, JWKS fetch, and a task-local
AuthCtx, wired with one.with_auth(...)call. Built for zero-trust networking. - Service Discovery — peer services resolve over Kubernetes DNS
(
<service>.<ns>.svc.cluster.local). No registry to run; cross-cluster routing stays in the mesh. - Cache — a
Cachetrait with a Redis-backed default and telemetry-wrapped operations. Swap the engine intonin.toml. - Database — a
Databasetrait with a Postgres default viasqlx, plus a rendered StatefulSet, Service, and injected credentials. - Event Bus — an
EventBustrait with ack/nack semantics for async, event-driven communication. Redis → NATS is a config change, not a rewrite. - Dynamic Config — load and hot-reload app config from env, etcd, GitHub, or chained
sources behind one
Configtrait. - Secrets — a
SecretStoretrait over an env-backed default, with required keys declared intonin.toml. - Background Jobs —
jobs::bootstrapplus generated Kubernetes CronJobs for scheduled and async work. - Helm Chart Generation — Deployment, Service, HPA, Ingress, and mesh overlays
rendered from
tonin.tomlwithtonin helm generate. Built into the CLI — no separate plugin needed. - Multi-Language Clients — generate Rust, Python, and TypeScript service skeletons
and client SDKs from the same
.proto. - Pluggable Interfaces — every capability above is a trait in
tonin-sdkwith implementations selected byengine = "...". Defaults are good; nothing is welded in.
Intentionally delegated to the service mesh: mTLS, retries, circuit breaking, and cross-cluster routing. tonin renders the right overlays and stays out of the network's way rather than reimplementing what Cilium/Istio/Linkerd already do well.
Pre-built archives are published for Linux (x86_64, ARM64), macOS (Intel, Apple Silicon), and Windows (x86_64) on every release. Helm chart generation is built in — no extra plugin needed.
macOS / Linux (bash):
curl -sSfL https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.sh | bashWindows (PowerShell — no Git Bash required):
py -3 -c "import urllib.request; exec(urllib.request.urlopen('https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.py').read())"Any platform (Python 3):
curl -sSfL https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.py | python3Or after cloning:
python3 scripts/install.pyCustom install directory — macOS / Linux:
curl -sSfL https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.sh \
| bash -s -- --dir /usr/local/binCustom install directory — Windows PowerShell:
python3 scripts/install.py --dir $env:USERPROFILE\.local\binVia cargo-binstall:
cargo binstall toninBuild from source:
cargo install tonintonin upgradePreview the plan without making changes:
tonin upgrade --checktonin upgrade discovers plugins on your $PATH, shows an upgrade plan, asks for
confirmation (--yes to skip), then runs the install script for each. Re-running the
install script directly works too — it detects the current version and skips if already
up to date.
You write three files:
- a
.proto— the wire contract - a handler
impl— your business logic - a
tonin.toml— service name, replicas, mesh, capabilities
tonin generates and wires everything else from those three, and keeps it all in sync:
- the Dockerfile and Helm charts (Deployment, Service, HPA, Ingress)
- the service-mesh overlay for Cilium, Istio, or Linkerd
- OpenTelemetry tracing and structured logs, with trace context propagated across calls
- the MCP tool server — every gRPC method exposed as an LLM-callable tool
- JWT auth — bearer extraction, validation, JWKS fetch, and request-scoped identity
- StatefulSets for your Postgres / Redis dependencies, with credentials injected
- client SDKs in Rust, Python, or TypeScript from the same proto
The network concerns it deliberately doesn't implement — mTLS, retries, circuit breaking, cross-cluster routing — are delegated to your service mesh, where they belong.
tonin.toml is the source of truth: re-run tonin helm generate after editing it rather
than hand-editing the generated charts.
Scaffold a new service:
tonin service new <name>Scaffold from a GitHub template repo:
tonin service new <name> --template-repo github.com/Org/repoRe-run codegen after editing .proto:
tonin proto generateRender Helm charts from tonin.toml:
tonin helm generateDetect drift between tonin.toml and rendered charts:
tonin helm checkThe CLI binary is tonin. See tonin --help for the full surface.
tonin service new has built-in templates compiled into the binary. For production use, pass
--template-repo to download templates from a GitHub repository at scaffold time:
Standard templates:
tonin service new my-svc --lang rust --template-repo github.com/Rushit/tonin-templatesPin to a release tag:
tonin service new my-svc --lang rust --template-repo github.com/Rushit/tonin-templates@v0.4.0Custom or private template repo:
tonin service new my-svc --lang rust --template-repo github.com/myorg/my-templatesThe flag accepts github.com/Org/repo or just Org/repo. Append @ref for a branch or tag
(@v0.4.0 is a tag; @my-branch is a branch). The CLI downloads the tarball, checks
version.toml for cli_min_version compatibility, and renders variants/default/<lang>/
(or variants/flat/<lang>/ when --flat is passed).
Template repos must follow the variants/default/<lang>/ layout — see
tonin-templates as the reference.
proto/greeter.proto:
syntax = "proto3";
package greeter.v1;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest { string name = 1; }
message HelloReply { string message = 1; }build.rs:
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonin_build::compile(&["proto/greeter.proto"], &["proto"])
}src/main.rs:
use tonin::prelude::*;
use greeter_server::{
auth,
gen::greeter_v1_server::GreeterServer,
server::{GreeterImpl, GreeterImplMcpAdapter},
};
#[tokio::main]
async fn main() -> tonin::Result<()> {
let state = State::from_env().await?;
let handler = GreeterImpl::new(state);
let mcp_handler = handler.clone();
Service::new("greeter")
.with_auth(auth::verifier())
.enable_mcp_with(move || Ok(GreeterImplMcpAdapter::new(mcp_handler.clone())))
.handler(GreeterServer::new(handler))
.run()
.await
}tonin.toml:
[service]
name = "greeter"
version = "0.1.0"
codec = "prost"
[deploy]
replicas = 2
mesh = "cilium"
mcp_sidecar = true
namespace = "default"
[resources]
cpu = "100m"
memory = "128Mi"Full source: examples/greeter.
Capabilities are declared in tonin.toml. Traits live in tonin-sdk;
implementations live in their own crates and are picked by engine = "...".
Swapping a backend is a TOML change plus a Cargo.toml dep flip — handler
code does not change.
[database]
engine = "postgres"
size = "10Gi"
[cache]
engine = "redis"
[secrets]
required = ["STRIPE_API_KEY"]See docs/01-principles.md for the interface-first
design rationale, and docs/07-cache.md through
docs/10-secrets.md for each capability's trait, TOML
schema, and status.
| Crate | Role |
|---|---|
tonin |
Umbrella re-export + CLI binary. use tonin::prelude::*; is what most services pull in. |
tonin-sdk |
Service builder, runtime, capability traits, auth, telemetry, MCP, transport, discovery. |
tonin-plugin |
Minimal tonin.toml Plan API for plugin authors. No CLI deps. |
tonin-client |
Tiny peer-service client primitives. No server framework deps. |
tonin-mcp-macros |
#[mcp_expose] proc-macro: auto-derives an MCP adapter from a gRPC impl block. |
tonin-build |
build.rs helper that wraps tonic-build with tonin conventions. |
Reader-facing docs live in docs/ — start with
00-overview.md, then 01-principles.md
for the four design rules (interface-first, mesh-delegated, MCP-by-default,
tonin.toml as the single source of truth). Each capability has its own doc with a
Status block listing what ships today vs. what's planned. Per-crate API reference is on
docs.rs.
See CONTRIBUTING.md for dev setup, PR conventions, and the scope of changes welcome at this stage. We follow Contributor Covenant 2.1.
To report a vulnerability, follow SECURITY.md. Don't open a public issue
with exploitable details — use the [security] tag flow described there so a maintainer
can reach out privately.
Apache-2.0. See LICENSE.