Skip to content

Rushit/tonin

tonin

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.

crates.io docs.rs CI License

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.


Why tonin

If you're a solo developer or a small team, your scarcest resource is you. tonin is built around that constraint:

  • One .proto in, 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 | bash
tonin service new greeter
cd greeter && cargo run

That'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.


Capabilities

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 Cache trait with a Redis-backed default and telemetry-wrapped operations. Swap the engine in tonin.toml.
  • Database — a Database trait with a Postgres default via sqlx, plus a rendered StatefulSet, Service, and injected credentials.
  • Event Bus — an EventBus trait 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 Config trait.
  • Secrets — a SecretStore trait over an env-backed default, with required keys declared in tonin.toml.
  • Background Jobsjobs::bootstrap plus generated Kubernetes CronJobs for scheduled and async work.
  • Helm Chart Generation — Deployment, Service, HPA, Ingress, and mesh overlays rendered from tonin.toml with tonin 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-sdk with implementations selected by engine = "...". 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.


Install the CLI

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 | bash

Windows (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 | python3

Or after cloning:

python3 scripts/install.py

Custom install directory — macOS / Linux:

curl -sSfL https://raw.githubusercontent.com/Rushit/tonin/main/scripts/install.sh \
  | bash -s -- --dir /usr/local/bin

Custom install directory — Windows PowerShell:

python3 scripts/install.py --dir $env:USERPROFILE\.local\bin

Via cargo-binstall:

cargo binstall tonin

Build from source:

cargo install tonin

Update

tonin upgrade

Preview the plan without making changes:

tonin upgrade --check

tonin 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.

What you write vs. what tonin handles

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.

Everyday commands

Scaffold a new service:

tonin service new <name>

Scaffold from a GitHub template repo:

tonin service new <name> --template-repo github.com/Org/repo

Re-run codegen after editing .proto:

tonin proto generate

Render Helm charts from tonin.toml:

tonin helm generate

Detect drift between tonin.toml and rendered charts:

tonin helm check

The CLI binary is tonin. See tonin --help for the full surface.

Scaffolding from a template repo

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-templates

Pin to a release tag:

tonin service new my-svc --lang rust --template-repo github.com/Rushit/tonin-templates@v0.4.0

Custom or private template repo:

tonin service new my-svc --lang rust --template-repo github.com/myorg/my-templates

The 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.

Example: hello-world service

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.

Adding capabilities

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 map

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.

Documentation

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.

Contributing

See CONTRIBUTING.md for dev setup, PR conventions, and the scope of changes welcome at this stage. We follow Contributor Covenant 2.1.

Security

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.

License

Apache-2.0. See LICENSE.

About

The one-person framework for Kubernetes microservices or MCP server.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors