Pipestream AI / ProtoMolt

Protocol Buffers at runtime.
A schema registry on Git.

ProtoMolt is a modular Java toolkit that loads, validates, reshapes, indexes, and serves protobuf messages from descriptors rather than generated classes — and a schema registry that stores every version as a Git commit while speaking the Confluent protocol your serializers already use.

Forty-seven focused modules under one BOM, MIT-licensed, artifacts under ai.pipestream on Maven Central. Every claim on this page is enforced by CI, not asserted.

JDK 21 baseline protovalidate 2872/2872 1,800+ tests per build Confluent protocol MCP MIT

Run it now

One container is the whole thing: gRPC with reflection, JSON/REST with Swagger UI, an MCP endpoint, and a schema registry — with a sample schema seeded so every verb has something to say immediately.

docker run -p 8080:8080 -p 9090:9090 ghcr.io/ai-pipestream/protomolt-serve --demo
# Validate a message against the demo schema's declared rules:
curl -s -H 'content-type: application/json' \
  -d '{"schema": {"type": "demo.shop.v1.Order"}, "message": {"id": "not-a-uuid"}}' \
  http://localhost:8080/grpc-json/ProtoMoltService/ValidateMessage

# Any gRPC client sees a real, reflectable service:
grpcurl -plaintext localhost:9090 list

# Make an AI agent gRPC-aware with one command:
claude mcp add --transport http protomolt http://localhost:8080/mcp

Swagger UI lives at localhost:8080/docs. Releases also attach runnable zips (JRE 21+ only). Then take a tutorial: Python clients without protoc or operating an OpenVINO server from an AI agent.

What it does

Use one module, or use the whole loop: gather → validate → register → serve → index.

descriptor-native core

Every code path works on Descriptor / FileDescriptor. A DynamicMessage resolved at runtime behaves exactly like a compiled-in type.

gathering

Filesystem trees, jars, Git repositories, Maven coordinates, Confluent and Apicurio registries. Text sources compile to descriptors at runtime, no protoc.

the registry

One commit per registration. History, review, and recovery are just Git; clients see the Confluent subjects API, and gRPC consumers fetch binary descriptor sets.

compatibility

A typed diff engine with 35 named rules classifies changes by wire, JSON, and source impact under all registry modes, including transitive.

validation

Rules travel as descriptor options. The protovalidate dialect passes the complete conformance suite, re-scored by buf’s own runner in CI.

publishing

Confluent and Apicurio publishers with topological reference registration, idempotent re-publish, and dry runs. Git stays the source of truth.

indexing hints

A descriptor-option standard for how fields come to rest in an index: analyzers, ranges, kNN vectors, map policies. Generates Lucene, OpenSearch, and Solr schemas.

mapping & CEL

Text mapping rules for reshaping messages, CEL filters and selectors where expressions matter, plus declared-metadata extraction.

JSON at the edge

A framework-agnostic REST gateway with OpenAPI 3 and JSON Schema generation, hosted on any of six servers. Inside the toolkit, everything stays binary.

Concrete examples

The same four steps a team actually takes, in the order they take them.

1 — Gather protos from a Git repo and compile them at runtime

ProtoGatherer gatherer = GitProtoGatherer.builder()
        .repo("https://github.com/acme/schemas.git")
        .ref("main")
        .subdir("proto")
        .build();

CompiledProtos compiled = ProtoSourceCompiler.compile(gatherer.gather());
DescriptorRegistry registry = DescriptorRegistry.create();
registry.addLoader(new GatheringDescriptorLoader(gatherer));

2 — Run a schema registry over a bare Git repository

var store  = GitSchemaRegistryStore.open(Path.of("/srv/schemas.git"));
var server = new SchemaRegistryServer(config, store,
        ActionCatalog.defaults(ActionContext.create()));
server.start();

Any Confluent-compatible client now works against it, and every registration is a commit:

curl -s -X POST localhost:8081/subjects/orders-value/versions \
     -H 'Content-Type: application/vnd.schemaregistry.v1+json' \
     -d @order.json
# gRPC consumers skip JSON entirely:
curl -s localhost:8081/protomolt/subjects/orders-value/descriptor-set -o orders.dsc

3 — Gate a change before it ships

var checker = CompatibilityChecker.builder().build();
var result  = checker.check(oldSources, newSources, CompatibilityMode.BACKWARD);

// A removed field surfaces as a typed change, not a diff hunk:
// FIELD_REMOVED at orders.Order.discount_code
//   impacts: [WIRE_BACKWARD, JSON_BACKWARD]

The registry runs the same engine on every write, so what passes locally registers cleanly.

4 — Depend on it

dependencies {
    implementation platform('ai.pipestream:protomolt-bom:<version>')
    implementation 'ai.pipestream:protomolt-registry-server'
    implementation 'ai.pipestream:protomolt-compat'
}

One BOM aligns all forty-two modules. Pick the two you need today; the rest are there when you need them.

Any gRPC service, agent-operable

Point an AI agent at a running gRPC service and let it operate the service.

protomolt-mcp serves the whole toolkit over the Model Context Protocol: thirteen tools on plain-Java stdio, or over streamable HTTP from a running protomolt-serve — one process makes every agent on the network gRPC-aware, no local install (claude mcp add --transport http protomolt http://host:8080/mcp). The schema registry is browsable as resources. Three of those tools close the loop on live services — reflect discovers a server’s schema from its address, grpc-invoke calls any unary or server-streaming method with no generated stubs on either side, and generate-stubs emits compilable clients in eight languages by running every libprotoc generator as WebAssembly inside the JVM.

When a server does not enable reflection — OpenVINO Model Server, NVIDIA Triton, and many production services do not — the agent falls back to the schema the project publishes: gather the .proto from its Git repository, register it once, and every step after that works identically. The advanced tutorial walks the entire path against a real OpenVINO server, ending with a live text → embedding inference driven through the agent.

Meta for meta: the gRPC service of itself

gRPC is defined in protobuf. So is ProtoMolt’s future API surface.

Every operation — compile, validate, diff, check compatibility, render schemas, evaluate CEL, reflect, invoke, generate — is a named action with a machine-readable input schema, and the catalog is now literally a gRPC service: ai.pipestream.protomolt.v1.ProtoMoltService, thirteen typed RPCs defined in .proto. The server compiles its own definition at startup and serves it over dynamic messages — no generated stubs anywhere — with server reflection on, so grpcurl, any gRPC client, or ProtoMolt’s own reflect verb discovers it. The tool that manages the format is spoken in the format.

One launcher, protomolt-serve, mounts the same thirteen verbs everywhere at once: gRPC with reflection, the JSON/REST gateway with a generated OpenAPI document, Swagger UI at /docs, and optionally the git-backed registry — every envelope identical across gRPC, REST, and MCP. The test suite pins the punchline: ProtoMolt operates a second live instance of itself through its own invoke verb.

Verification, not assertion

1,800+ tests run in the standard build. The complete protovalidate conformance suite is re-scored with buf’s own runner on every push. Live-registry integration suites run against real Apicurio and Confluent registries in CI — and fail the build if they silently skip.