mcp server
agentic-registry
Gateway-neutral registry for agentic artifacts (skills, tools, MCPs, prompts, workflows, blueprints)
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 21, 2026Agentic Registry
An open, self-hostable, gateway-neutral registry & marketplace for agentic artifacts.
Skills · Tools · MCP Servers · Prompts · Workflows · Blueprints · Agents
Quick start · How it works · The catalog · API · CLI · Self-host · Security
What is this?
Agentic Registry is the control plane for your agentic artifacts — one place to publish, version, discover, and govern the building blocks your agents are made of: skills, tools, MCP servers, prompts, workflows, blueprints, and agents.
It is deliberately a catalog, not a proxy.
It stores and serves metadata + bytes and answers discovery queries. It never authenticates end-user traffic, mints tokens, proxies requests, or runs the artifacts it catalogs. Every gateway integration is an adapter that reads from the registry — never a coupling baked into it.
That single invariant is what makes it gateway-neutral: point Portkey, agentgateway, kagent, an MCP aggregator, or your own runtime at the same registry and each reads what it needs.
Why it exists
Every existing registry leaves a gap:
| Project | The gap |
|---|---|
| Portkey | Open-sources the proxy — keeps the registry (prompts, model catalog, configs) proprietary. |
| solo.io aregistry | Couples the registry tightly to its own agentgateway. |
| Official MCP Registry | Explicitly not built for self-hosting. |
Agentic Registry is the missing piece: an open, self-hostable control plane you run yourself and point any agentic gateway at.
Features
- One envelope, seven kinds — every artifact is a Kubernetes-style
apiVersion/kind/metadata/specdocument. Skills, Tools, MCP Servers, Prompts, Workflows, Blueprints, and Agents all share the same shape, so one publish/discover flow covers everything. - Content-addressed & idempotent — bytes are stored by SHA-256; re-applying the same
content is a no-op. OCI-style tags (
latestby default) instead of semver-in-path. - Label-selector discovery — the Kubernetes
LabelSelectorgrammar, verbatim (matchLabels+matchExpressions,In | NotIn | Exists | DoesNotExist). - Multi-tenant by design —
tenant → org → teamownership ×public | internal | privatevisibility × cumulativeread < write < adminRBAC. - Two interop dialects — a devai-compatible
/v0/*API and the official MCP-Registry/v0.1/*Generic Registry API (server.jsonis the MCPServerspec, natively). - Prompt render —
POST /v0/prompts/{name}/renderreturns a ready-to-send{ model, messages, params, tools }payload built with logic-less Mustache templating. Send it to whatever gateway you like. - Signed responses — the registry signs what it serves;
agentic verifychecks the signature. - A2A agent cards — agents expose a
.well-known/agent-card.jsonfor Agent-to-Agent discovery. - Gateway adapters — export live registry state to a runtime's native config
(
agentgateway,kagent) without the registry ever being on the request path. - Built-in MCP discovery server — agentic IDEs browse the catalog through MCP itself
(
list_skills,get_server,search_registry, …) over stateless MCP2026-07-28; the legacy initialize path remains compatibility-only. - Digest-safe capability probing —
server/discoverand self-containedtools/listqualify routed servers without sessions; legacy-only servers cannot become ready. - Registry-owned semantic discovery — pgvector ranks a secret-safe projection of capability annotations, relationships, tags, and Tool schemas; gateways fetch exact hits progressively.
- Marketplace UI +
agenticCLI — browse in the web app;init/apply/push/pull/renderfrom the terminal.
How it works
Publishers push artifacts in; gateways and IDEs read them out. The registry sits in the middle as a catalog — never on the live request path.
┌───────────────────────────────────────────┐
publishers ──CLI/API─▶│ agentic-registry (Go) │
(devai, you, CI) │ │──▶ Postgres
│ ingest → normalize envelope → SHA-256 │ (catalog: JSONB
┌── discovery ───────▶│ store bytes → index labels │ + GIN-indexed labels)
│ │ │
│ gateways │ /v0/* devai-compat dialect │──▶ object store
│ IDEs (via MCP) │ /v0.1/* MCP Generic Registry dialect │ (bytes, content-addressed)
│ MCP aggregators │ built-in MCP discovery server │
│ │ prompt render · A2A cards · adapters │
└─────────────────────└───────────────────────────────────────────┘
identity comes FROM the edge: trusted X-Forwarded-* from a gateway,
OR a JWKS-verified Bearer JWT. The registry issues no tokens.
The lifecycle of one artifact:
- Author — write a manifest (or
agentic init Skill my-skillto scaffold one). - Publish —
agentic apply -f skill.yaml. The server normalizes the apiVersion group, computes a content hash, stores the bytes, and indexes the labels. - Version — same name + new tag = a new immutable revision. Same content = idempotent no-op. The full revision timeline is append-only.
- Discover — gateways/IDEs query by kind + label selector. Visibility/RBAC is applied before the selector — the selector is discovery convenience, never a security boundary.
- Consume — a gateway pulls config via an adapter, an IDE browses via the MCP discovery server, or a runtime fetches a rendered prompt. The registry just serves; it never runs anything.
The catalog
Seven kinds, one envelope
apiVersion: registry.agentic.dev/v1alpha1
kind: Skill # Skill | Tool | MCPServer | Prompt | Workflow | Blueprint | Agent
metadata:
name: senior-developer
namespace: default # maps to a tenant scope
tag: latest # OCI-style; same tag re-applies atomically
labels: { domain: code-review, language: go }
visibility: public # public | internal | private
spec: { ... } # kind-specific body
status: { ... } # server-managed (content hash, timestamps, signature)
| Kind | What it catalogs |
|---|---|
| Skill | A reusable agent capability (prompt + metadata + source pointer). |
| Tool | A callable function/tool definition. |
| MCPServer | An MCP server — the spec is a server.json (packages/remotes, transports), so it round-trips with the official MCP Registry. |
| Prompt | A versioned, renderable prompt template (Mustache) with movable labels (production/staging). |
| Workflow | A multi-step orchestration of skills/tools. |
| Blueprint | A composable bundle/recipe of the above. |
| Agent | A devai-interop agent definition; exposes an A2A agent card. |
Three orthogonal axes
The data model separates who owns it, who can see it, and how you find it:
- Scope (ownership) —
tenant_id(required) →org_id→team_id. Users join teams; teams live in orgs (the Docker Hub model). Reverse-DNS namespaces, ownership-verified. - Visibility —
public | internal | private.internal= the whole tenant;public⇒ anonymous read, no token required. - Labels — freeform user labels for discovery, plus server-managed immutable system
labels (
tenant,org,visibility) that publishers cannot spoof.
The access decision (the security boundary)
can_read(artifact, caller) =
artifact.visibility == public
OR (artifact.visibility == internal AND caller.tenant == artifact.tenant)
OR rbac_grant(read|write|admin, artifact, caller)
Roles are cumulative: read < write < admin.
Quick start
# 1. Run it locally — zero dependencies (in-memory store):
make run # API on http://localhost:8080
curl localhost:8080/v0/health
# 2. Publish your first artifact:
go run ./cmd/agentic apply -f examples/skill.yaml
# 3. Discover it:
curl 'localhost:8080/v0/skills?labelSelector=domain%20in%20(code-review)'
Prefer containers? Bring up the full stack (Postgres + API + UI):
docker compose -f deploy/docker-compose.yml up
Pull the published image directly from GHCR (no auth — it's public):
docker pull ghcr.io/tesserix/agentic-registry:latest
The agentic CLI
agentic login --registry URL [--token TOKEN]
agentic init <kind> <name> scaffold a manifest (Skill|Tool|MCPServer|Prompt|Workflow|Blueprint|Agent)
agentic apply -f <file.yaml> publish a multi-doc YAML bundle (kubectl-apply style)
agentic push <file.yaml> publish a single resource
agentic list <plural> [--selector S] list a collection (table; -o json for raw)
agentic pull <plural> <name> [--tag T] fetch one artifact (omit --tag for latest)
agentic versions <plural> <name> list all published versions (tags)
agentic history <plural> <name> show the append-only revision timeline
agentic search <query> cross-kind ranked search
agentic render <name> [-f vars.json] render a Prompt with variables
agentic verify <plural> <name> [--tag T] verify the registry's signature
agentic export <target> <agent> render an agent for a runtime (kagent | agentgateway)
agentic status registry endpoint, health, signing key
Config lives in ~/.agentic/config.json. Overridable via AGENTIC_REGISTRY,
AGENTIC_TOKEN, and AGENTIC_INSECURE.
API surface
/v0/* — devai-compatible dialect
GET /v0/health
GET /v0/{plural}[?namespace=&labelSelector=] list a kind (skills|tools|mcpservers|prompts|workflows|blueprints|agents|datasets|evalsuites)
POST /v0/{plural} publish a single resource
GET /v0/{plural}/{name} latest tag
GET /v0/{plural}/{name}/{tag} a specific tag
GET /v0/{plural}/{name}/tags list tags
GET /v0/{plural}/{name}/revisions append-only revision timeline
DELETE /v0/{plural}/{name}/{tag} delete one version
POST /v0/apply multi-doc YAML batch (apply)
DELETE /v0/apply multi-doc YAML batch (delete)
POST /v0/prompts/{name}/render → { model, messages, params, tools }
GET /v0/search?q=&kinds=&limit=&view=stub ranked safe stubs with exact fetch paths
GET /v0/signing-key public key the registry signs with
GET /v0/agents/{name}/.well-known/agent-card.json A2A agent card
GET /v0/{plural}/{name}/resolved fully-resolved artifact (refs expanded)
GET /v0/export/agentgateway export catalog as agentgateway config
GET /v0/export/kagent export agents as kagent resources
servers, mcpservers, and mcp-servers alias MCPServer; evalsuites and eval-suites
alias EvalSuite. The apiVersion group is normalized on ingest. Omitting view=stub on search
retains the artifact-envelope response for compatibility.
/v0.1/* — MCP Generic Registry interop (verbatim)
GET /v0.1/health
GET /v0.1/servers?cursor=&limit=&search=&updated_since=&version=
GET /v0.1/servers/{serverName}/versions
GET /v0.1/servers/{serverName}/versions/{version} ('latest' allowed)
POST /v0.1/publish Bearer JWT; body = server.json
PATCH /v0.1/servers/{serverName}/versions/{version}/status active | deprecated | deleted
Cursor pagination via metadata.nextCursor; incremental sync via updated_since.
Self-hosting
Everything you need to copy and run is in k8s/:
k8s/secrets.example.yaml— the single Secret to fill in.k8s/README.md— copy-and-go steps.docs/deploy.md— local-kind, Helm, and ArgoCD paths.
The server is a single distroless static Go binary. In production it pairs with Postgres (catalog) and an object store (bytes); secrets come from a secret manager via External Secrets — never the database, never the image.
More guides:
docs/agentgateway-admin.md— administer AgentGateway and connect products.docs/connecting-tools.md— wiring a gateway/tool to the registry.docs/cli.md— the full CLI reference.docs/a2a-agent-cards.md— Agent-to-Agent discovery.
Security model
The architecture is the security posture. The registry:
- does not mint tokens, authenticate end-user traffic, or proxy requests;
- stores no secrets in its database — provider credentials are kept only as references to an external secret manager;
- accepts identity from the edge — a trusted
X-Forwarded-*header from a gateway (over mTLS / a known gateway only), a Bearer JWT verified against a configurable JWKS/issuer, or an opaque tenant-scoped deploy key sent inX-Agentic-Registry-Deploy-Keywhose SHA-256 digest is stored by the server; - applies the visibility/RBAC filter before any label selector, so discovery can never widen access.
Found a vulnerability? See SECURITY.md — please report privately, do not open a public issue. Reports about secret leakage, RBAC bypass, or namespace-ownership spoofing are treated as high severity.
Machine publishers can use AUTH_DEPLOY_KEYS with comma-separated
tenant=sha256-digest entries. Repeating a tenant allows old and new keys to
overlap during rotation. Keep the raw key only in the publisher's secret store;
the registry compares its digest in constant time and grants only
registry:read registry:write within the configured tenant.
Authorization: Bearer deploy keys remain supported for clients outside a
JWT-validating mesh, but machine publishers behind the mesh must use the
dedicated header so opaque credentials are not parsed as JWTs.
Human administration can additionally require two independent Zitadel claims:
an exact AUTH_ADMIN_EMAILS match and the project role named by
AUTH_ADMIN_ROLE. This mapping understands Zitadel's project-role object claim
and does not affect tenant-scoped deploy keys or scoped machine identities. See
docs/adr/0002-zitadel-admin-and-machine-integration-boundaries.md.
Tenant publishers sign in interactively with agentic auth login. For CI,
users create a short-lived, namespace/kind-scoped credential under Settings →
API credentials and configure AGENTIC_CLIENT_ID,
AGENTIC_CLIENT_SECRET, AGENTIC_TOKEN_URL, and AGENTIC_AUDIENCE. The CLI
exchanges those values for a short-lived token in memory; it never persists the
client secret. See the CLI credential setup.
Contributing & governance
Contributions are welcome — start with CONTRIBUTING.md and the Code of Conduct.
- Branch + PR off
main; every commit must be signed off (git commit -s, DCO). - CI must be green: Go build/vet/test, web build, secret scan (gitleaks), and CodeQL.
- This project is maintained by a single maintainer (@Sam123ben);
all merges and approvals to
maingo through them.mainis protected and requires a passing review + checks.
The architectural invariant is non-negotiable: any change that routes traffic, mints tokens, or runs artifacts will be rejected. The registry stays a catalog.
License
Apache-2.0. See also NOTICE.