This document defines the AI Catalog, a JSON format for discovering heterogeneous AI artifacts such as MCP servers, A2A agents, Claude Code plugins, datasets, and model cards. Each catalog entry declares the artifact's type via a media type and references or inlines the native artifact metadata, enabling a single discovery mechanism across protocols and platforms. The specification defines three conformance levels — Minimal, Discoverable, and Trusted — allowing implementations to start with a simple list of entries and progressively add host identity, well-known URI discovery, and verifiable trust metadata as needed. An optional Trust Manifest extension provides identity binding, compliance attestations, provenance tracking, and cryptographic signatures without wrapping or modifying the artifact's native format. Informative appendices describe mappings to OCI distribution registries, the MCP Registry server.json format, and the Claude Code Plugins marketplace.
This is a draft document and may be updated at any time.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [[RFC2119]] [[RFC8174]] when, and only when, they appear in all capitals, as shown here.
The AI ecosystem comprises a growing number of protocols, artifact formats, and service types. Model Context Protocol (MCP) servers, Agent-to-Agent (A2A) agents, Claude Code plugins, datasets, model cards, and other AI artifacts each define their own metadata and discovery mechanisms. This fragmentation forces clients and registries to implement bespoke logic for each artifact type, increasing complexity and reducing interoperability.
This document defines the AI Catalog: a typed, nestable JSON container for discovering heterogeneous AI artifacts. Each entry declares its artifact type via a media type and may reference or inline the native artifact metadata. A minimal catalog is simply a list of entries — names, types, and URLs — requiring no additional infrastructure.
For environments that need verifiable identity, compliance evidence, or provenance tracking, this document also defines an optional Trust Manifest extension. A Trust Manifest accompanies an artifact as a peer element, carrying attestations and provenance metadata without wrapping or modifying the artifact's native format. Implementations that do not need trust metadata can ignore the Trust Manifest entirely.
The AI Catalog is intentionally agnostic about the artifacts it indexes. It does not define or constrain the schema of MCP server manifests, A2A agent cards, or any other artifact format. Instead, it relies on media types to identify what each entry is, and delegates the definition of artifact-specific metadata to the respective protocol specifications.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [[RFC2119]] [[RFC8174]] when, and only when, they appear in all capitals, as shown here.
The following terms are used throughout this document:
application/ai-catalog+json
media type that contains an ordered list of catalog entries.Artifact Agnosticism: The catalog MUST be capable of indexing any type of AI artifact without requiring knowledge of the artifact's internal schema.
Media Type Identification: Each catalog entry MUST declare its artifact type using a media type, enabling clients to select, filter, and route entries without parsing artifact content.
Composability: The catalog format supports nesting — a catalog entry can reference another AI Catalog. This enables plugin-style packaging where a single catalog bundles multiple related artifacts.
Progressive Complexity: The simplest catalog is just entries with names and URLs. Trust, identity, and provenance metadata are available as optional extensions that never modify the catalog structure or artifact formats.
Scalable Federation: The catalog format enables partitioning into sub-catalogs to manage size, and supports delegation to sub-catalogs managed by independent publishers. Collections and nested catalogs support a federated model where each segment of the hierarchy may be authored, hosted, and updated independently.
Location Independence: An AI Catalog MAY be served from any URL. The standard defines a well-known URL convention to enable automated discovery, but catalogs are equally valid when hosted at arbitrary paths, embedded in registries, or distributed as files.
An AI Catalog document is identified by the media type:
application/ai-catalog+json
An AI Catalog document is a JSON object that MUST contain the following members:
specVersionentriesFor example, a minimal catalog listing three AI artifacts:
{
"specVersion": "1.0",
"entries": [
{
"identifier": "urn:example:skill:code-review",
"displayName": "Code Review Assistant",
"mediaType": "application/ai-skill",
"url": "https://skills.example.com/code-review/skill.zip"
},
{
"identifier": "urn:example:mcp:weather",
"displayName": "Weather Service",
"mediaType": "application/mcp-server+json",
"url": "https://api.example.com/.well-known/mcp/server-card.json"
},
{
"identifier": "urn:example:a2a:research",
"displayName": "Research Assistant",
"mediaType": "application/a2a-agent-card+json",
"url": "https://agents.example.com/researchAssistant"
}
]
}
The following members are OPTIONAL:
hostcollectionsmetadataThe Host Info object identifies the operator of the catalog. It MUST contain:
displayNameThe following members are OPTIONAL:
identifierdocumentationUrllogoUrltrustManifestA Catalog Entry object describes a single AI artifact in the catalog. It MUST contain the following members:
identifierurn:example:agent:name).
See Multi-Version Entries for uniqueness
rules when multiple versions are present.displayNamemediaTypeapplication/ai-catalog+json — a nested AI Catalogapplication/a2a-agent-card+json — an A2A Agent Cardapplication/mcp-server+json — an MCP Server manifestapplication/ai-skill for skill definitions)A Catalog Entry MUST contain exactly one of the following members to provide the artifact content:
urlmediaType field.inlinemediaType field and
is opaque to this specification.The following members are OPTIONAL:
descriptiontagsversionidentifier.updatedAtmetadatapublishertrustManifestA catalog MAY contain multiple entries with the same identifier and
different version values, representing a version history for a
single artifact — similar to a package registry.
When version is present, the combination of identifier and version
MUST be unique within the catalog. When version is absent, identifier
alone MUST be unique. The identifier SHOULD be stable across versions
and catalog locations so that the same logical artifact can be
recognized wherever it appears.
Clients that need only the latest version SHOULD sort entries
sharing the same identifier by version (when parseable as a semantic
version) or by updatedAt, and select the most recent. Clients
that need a specific version SHOULD match on both identifier and version.
The Publisher object identifies the entity responsible for an artifact. It appears on the Catalog Entry and is the canonical location for publisher information. It MUST contain:
identifierdisplayNameThe following members are OPTIONAL:
identityTypeThe Trust Manifest is an OPTIONAL companion to catalog entries and host objects. It is a JSON object that provides verifiable identity, attestation, and provenance metadata for AI artifacts. Implementations that do not require trust metadata MAY ignore this section entirely — a conformant AI Catalog does not require Trust Manifests.
The Trust Manifest does NOT wrap the artifact. It sits alongside the artifact as a peer element within a Catalog Entry, keeping the native artifact format unmodified. Publisher information is NOT duplicated in the Trust Manifest — the informational publisher identity is carried on the Catalog Entry (see Publisher Object).
A Trust Manifest MUST contain:
identityWhen a Trust Manifest appears within a Catalog Entry, the identity
field MUST match the entry's identifier field. This binding ensures trust
claims are unambiguously associated with the catalog artifact.
Consumers MUST reject a Trust Manifest whose identity does not
match the containing entry's identifier.
When a Trust Manifest appears on a Host Info object, identity
SHOULD match the host's identifier field when present.
When multiple entries share the same identifier (with different version
values), each entry MAY carry its own Trust Manifest. There is no
requirement that all versions carry identical trust metadata — trust
properties may evolve across versions.
The following members are OPTIONAL:
identityTypetrustSchemaattestationsprovenanceprivacyPolicyUrltermsOfServiceUrlsignaturemetadataA Trust Schema object describes the trust framework applied to the artifact. It MUST contain:
identifierversionThe following members are OPTIONAL:
governanceUriverificationMethodsAn Attestation object provides verifiable proof of a claim. It MUST contain:
typeurimediaTypeThe following members are OPTIONAL:
digestsizedescriptionA Provenance Link records lineage information. It MUST contain:
relationsourceIdThe following members are OPTIONAL:
sourceDigestregistryUristatementUrisignatureRefThis section describes how consumers verify the trust metadata carried by a Trust Manifest. Verification is OPTIONAL — consumers that do not need trust assurance can skip this entirely.
Digests in this specification use the format algorithm:hex-value,
where algorithm is a hash algorithm identifier and hex-value is
the lowercase hexadecimal encoding of the hash output. For example:
sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Producers SHOULD use SHA-256 [[RFC6234]] or stronger. Consumers MUST reject digest values using algorithms shorter than SHA-256.
The signature field carries a detached JWS [[RFC7515]] computed
over the Trust Manifest content. To create or verify a signature:
signature
field itself before canonicalization.signature field.This approach ensures the signature is stable regardless of JSON key ordering or whitespace, and can be verified independently of the artifact content.
Consumers resolve the signer's public key based on the identity
URI scheme:
did:web:example.com)verificationMethod
array.https://example.com/.well-known/jwks.json)kid header.spiffe://example.com/service)To verify the host of a catalog:
host.identifier is a DID, resolve the DID Document and confirm the
hosting domain appears in the DID Document's service endpoints.host.trustManifest is present and signed, verify the
signature as described above.To verify the publisher of an artifact:
publisher-identity attestation in the Trust
Manifest's attestations array.uri.publisher.identifier).publisher.identifier to the Trust
Manifest's identity.When a Trust Manifest includes provenance entries with sourceDigest:
url.sourceDigest field.For each attestation in the attestations array:
uri.digest is present, verify the fetched document matches the
declared digest.type (e.g., verify a JWT
signature, confirm a PDF certificate is current).As catalogs grow, a flat list of entries becomes unwieldy. This specification provides two complementary mechanisms for structuring catalogs at scale: bundles and collections. They serve fundamentally different purposes and appear in different parts of the document.
A bundle is a catalog entry whose mediaType is
application/ai-catalog+json. The entry's content (via url or
inline) is itself an AI Catalog document containing the bundled
artifacts. Bundles express dependency: the artifacts inside
are related and intended to be acquired or deployed together.
Use bundles when:
Vendor Catalog
└── Entry: "Finance Plugin" (mediaType: application/ai-catalog+json)
├── Entry: Finance A2A Agent
├── Entry: Finance MCP Server
└── Entry: Market Dataset
A bundle is a regular catalog entry — it has an identifier, may carry a
trustManifest, and may include a publisher. An entry inside a
bundle MAY reuse the same identifier as an entry elsewhere; this
indicates the same logical artifact.
Clients processing bundles SHOULD impose a maximum nesting depth to prevent circular references. A depth limit of 8 is RECOMMENDED.
Collections are an OPTIONAL top-level array on the AI Catalog. Each element is a Collection Reference that points to a child AI Catalog at a different URL. Collections express organization: they partition a large catalog into browsable subcategories without implying any dependency between the referenced catalogs.
Use collections when:
A Collection Reference object MUST contain:
displayNameurlThe following members are OPTIONAL:
descriptiontagsEnterprise Catalog
├── Collection: "Finance Services" → https://acme.com/catalogs/finance.json
├── Collection: "ML Models" → https://acme.com/catalogs/ml.json
└── Collection: "DevOps Tools" → https://acme.com/catalogs/devops.json
├── Collection: "CI/CD" → https://acme.com/catalogs/devops/cicd.json
└── Collection: "Monitoring" → https://acme.com/catalogs/devops/monitoring.json
Collections are recursive — a child catalog MAY itself contain
collections, enabling multi-level organizational hierarchies.
Clients SHOULD impose a maximum traversal depth.
| Bundle | Collection | |
|---|---|---|
| Where | An entry in entries[] |
An element in collections[] |
| Content | Inline or referenced AI Catalog | URL to a separate AI Catalog |
| Semantics | Dependency — artifacts are consumed together | Organization — catalogs are browsed independently |
| Identity | Has an identifier, may carry trustManifest |
Named pointer, no artifact identity |
| Example | "Finance Plugin" shipping agent + server + data | "Finance Department" grouping 50 artifacts |
| Trust | Bundle entry may have its own publisher and trust | Child catalog has its own host and publisher(s) |
A single catalog MAY use both mechanisms. For example, an enterprise catalog could use collections to partition by department, while individual department catalogs contain bundle entries that package related artifacts together.
An AI Catalog document MAY be served from any URL. It is identified
by its media type (application/ai-catalog+json) and its specVersion
field, not by its URL path. Catalogs are equally valid when hosted at
an arbitrary path, embedded in a registry response, bundled in a
package, or distributed as a local file.
When served over HTTP, the document SHOULD be served with the media
type application/ai-catalog+json.
To support automated discovery, hosts MAY serve an AI Catalog at the following well-known URI [[RFC8615]]:
/.well-known/ai-catalog.json
Clients performing domain-level discovery SHOULD attempt to retrieve
this well-known URL. If a valid AI Catalog document is returned, the
client SHOULD use the url entries to retrieve individual artifacts
and their associated Trust Manifests.
Use of the well-known URI is OPTIONAL. Hosts that publish catalogs at other locations (e.g., as part of an API response or a package registry) are fully conformant.
Implementing protocols MAY support dynamic catalog generation through their own mechanisms, such as providing different catalog content based on a caller's identity or query parameters. Defining dynamic discovery behavior is out of scope for this specification.
Websites MAY advertise their AI Catalog by including an ai-catalog
link relation in HTTP responses or HTML documents. This enables AI
agents, crawlers, and other automated clients to discover the catalog
associated with any website without prior knowledge of its location.
HTTP Link header. A server MAY include a Link header [[RFC8288]]
in HTTP responses:
Link: <https://example.com/catalog/ai.json>; rel="ai-catalog"
HTML <link> element. An HTML page MAY include a link element in
the document head:
<link rel="ai-catalog" href="/catalog/ai.json"
type="application/ai-catalog+json">
Agent-driven discovery. AI agents that interact with websites
(for example, agents following user instructions to "find tools on
this site" or browsing on behalf of a user) SHOULD check for the
ai-catalog link relation on the target website. The discovery
procedure is:
Link header with rel="ai-catalog".Link header is present and the response is an HTML
document, parse the document for a <link> element with
rel="ai-catalog"./.well-known/ai-catalog.json as described in
Well-Known URI.application/ai-catalog+json and contains a valid specVersion
field, treat it as the site's AI Catalog.This mechanism allows any website to surface its AI tools, agents, and services to visiting agents through a standard, machine-readable pointer — without requiring changes to the site's visible content.
This specification defines three conformance levels. Each level builds on the previous one. Implementations MUST satisfy all requirements of their declared level.
A conformant Minimal Catalog is a JSON document with media type
application/ai-catalog+json that contains:
specVersion — the specification version stringentries — an array of Catalog Entry objects, each containing at
minimum identifier, displayName, mediaType, and exactly one of url or
inlineAll other fields (host, collections, publisher, trustManifest,
metadata) are OPTIONAL. This level is sufficient for use cases that
only need a simple list of AI artifacts — for example, a catalog of
MCP servers or A2A agents.
In addition to Level 1 requirements, a Discoverable Catalog:
host object identifying the catalog operator/.well-known/ai-catalog.json
to enable automated domain-level discoverycollections for organizational hierarchyIn addition to Level 2 requirements, a Trusted Catalog:
trustManifest objects on entries and/or the host, as
defined in Trust Manifestpublisher objects on entries with verifiable identifiersImplementations at any level are fully conformant with this specification. Consumers MAY ignore fields defined at higher conformance levels and SHOULD gracefully handle their absence.
AI Catalogs, artifacts, and Trust Manifests MUST be served over HTTPS (TLS 1.2 or later) to prevent tampering and eavesdropping.
Clients processing nested catalogs MUST enforce a maximum recursion depth to prevent denial-of-service attacks via deeply nested or circular catalog references. A maximum depth of 8 is RECOMMENDED.
Logo URLs SHOULD use Data URIs [[RFC2397]] to avoid leaking client
information through image fetch requests. Publishers SHOULD carefully
consider what information is included in metadata extension fields.
The following diagram illustrates the relationships between the core objects defined in this specification:
classDiagram
class AICatalog {
specVersion string
entries CatalogEntry[]
host HostInfo
collections CollectionRef[]
}
class HostInfo {
displayName string
identifier string
trustManifest TrustManifest
}
class CatalogEntry {
identifier string
displayName string
mediaType string
url | inline
version string
publisher Publisher
trustManifest TrustManifest
}
class CollectionRef {
displayName string
url string
description string
tags string[]
}
class Publisher {
identifier string
displayName string
}
class TrustManifest {
identity string
trustSchema TrustSchema
attestations Attestation[]
provenance ProvenanceLink[]
signature string
}
class TrustSchema {
identifier string
version string
verificationMethods string[]
}
class Attestation {
type string
uri string
mediaType string
digest string
}
class ProvenanceLink {
relation string
sourceId string
sourceDigest string
}
AICatalog --> "*" CatalogEntry : entries
AICatalog --> "0..1" HostInfo : host
AICatalog --> "*" CollectionRef : collections
CatalogEntry --> "0..1" Publisher : publisher
CatalogEntry --> "0..1" TrustManifest : trustManifest
HostInfo --> "0..1" TrustManifest : trustManifest
TrustManifest --> "0..1" TrustSchema : trustSchema
TrustManifest --> "*" Attestation : attestations
TrustManifest --> "*" ProvenanceLink : provenance
CatalogEntry --> "0..1" AICatalog : bundle
CollectionRef ..> AICatalog : references
This section registers the application/ai-catalog+json media type
[[RFC6838]] in the "Application" registry.
specVersion and entries fields.This section registers the ai-catalog link relation type in the
IANA "Link Relations" registry [[RFC8288]].
application/ai-catalog+json)
that describes AI artifacts, agents, and services associated with
the context resource. See Link Relation Discovery.The following CDDL [[RFC8610]] defines the normative schema for AI Catalog and Trust Manifest documents.
AICatalog = {
specVersion: text,
? host: HostInfo,
entries: [* CatalogEntry],
? collections: [* CollectionRef],
? metadata: { * text => any }
}
HostInfo = {
displayName: text,
? identifier: text,
? documentationUrl: text,
? logoUrl: text,
? trustManifest: TrustManifest
}
CollectionRef = {
displayName: text,
url: text,
? description: text,
? tags: [* text]
}
CatalogEntry = {
identifier: text,
displayName: text,
mediaType: text,
(url: text // inline: any),
? version: text,
? description: text,
? tags: [* text],
? publisher: Publisher,
? trustManifest: TrustManifest,
? updatedAt: tdate,
? metadata: { * text => any }
}
Publisher = {
identifier: text,
displayName: text,
? identityType: text
}
TrustManifest = {
identity: text,
? identityType: text,
? trustSchema: TrustSchema,
? attestations: [* Attestation],
? provenance: [* ProvenanceLink],
? privacyPolicyUrl: text,
? termsOfServiceUrl: text,
? signature: text,
? metadata: { * text => any }
}
TrustSchema = {
identifier: text,
version: text,
? governanceUri: text,
? verificationMethods: [* text]
}
Attestation = {
type: text,
uri: text,
mediaType: text,
? digest: text,
? size: uint,
? description: text
}
ProvenanceLink = {
relation: text,
sourceId: text,
? sourceDigest: text,
? registryUri: text,
? statementUri: text,
? signatureRef: text
}
The following example shows an AI Catalog that contains a mix of artifact types including a nested catalog acting as a plugin bundle:
{
"specVersion": "1.0",
"host": {
"displayName": "Acme Services Inc.",
"identifier": "did:web:acme-corp.com",
"documentationUrl": "https://docs.acme-corp.com/ai"
},
"entries": [
{
"identifier": "urn:acme:agent:finance-a2a",
"displayName": "Acme Finance A2A Agent",
"version": "2.1.0",
"mediaType": "application/a2a-agent-card+json",
"url": "https://api.acme-corp.com/agents/finance.json",
"description": "A2A agent for financial workflows.",
"tags": ["finance", "a2a"],
"publisher": {
"identifier": "did:web:acme-corp.com",
"displayName": "Acme Financial Corp"
},
"trustManifest": {
"identity": "urn:acme:agent:finance-a2a",
"attestations": [
{
"type": "publisher-identity",
"uri": "https://trust.acme.com/certs/publisher.jwt",
"mediaType": "application/jwt",
"description": "Verifies did:web:acme-corp.com as publisher"
},
{
"type": "SOC2-Type2",
"uri": "https://trust.acme.com/reports/soc2.pdf",
"mediaType": "application/pdf",
"digest": "sha256:a1b2c3d4e5f6"
}
],
"privacyPolicyUrl": "https://acme.com/legal/privacy",
"termsOfServiceUrl": "https://acme.com/legal/terms"
},
"updatedAt": "2026-03-15T10:00:00Z"
},
{
"identifier": "urn:acme:server:finance-mcp",
"displayName": "Acme Finance MCP Server",
"version": "1.4.0",
"mediaType": "application/mcp-server+json",
"url": "https://api.acme-corp.com/mcp/finance.json",
"description": "MCP server with finance tools.",
"tags": ["finance", "mcp"],
"updatedAt": "2026-03-15T10:00:00Z"
},
{
"identifier": "urn:acme:plugin:finance-suite",
"displayName": "Acme Finance Suite",
"mediaType": "application/ai-catalog+json",
"description": "Plugin bundle: A2A agent + MCP server + dataset.",
"tags": ["finance", "plugin", "bundle"],
"inline": {
"specVersion": "1.0",
"entries": [
{
"identifier": "urn:acme:agent:finance-a2a",
"displayName": "Finance A2A Agent",
"mediaType": "application/a2a-agent-card+json",
"url": "https://api.acme-corp.com/agents/finance.json"
},
{
"identifier": "urn:acme:server:finance-mcp",
"displayName": "Finance MCP Server",
"mediaType": "application/mcp-server+json",
"url": "https://api.acme-corp.com/mcp/finance.json"
},
{
"identifier": "urn:acme:data:market-2026q1",
"displayName": "Market Dataset Q1 2026",
"mediaType": "application/parquet",
"url": "https://data.acme-corp.com/market-2026q1.parquet",
"trustManifest": {
"identity": "urn:acme:data:market-2026q1",
"provenance": [
{
"relation": "publishedFrom",
"sourceId": "oci://registry.acme.com/data/market:2026q1",
"sourceDigest": "sha256:99998888..."
}
]
}
}
]
},
"trustManifest": {
"identity": "urn:acme:plugin:finance-suite",
"signature": "eyJhbGciOiJFUzI1NiJ9..detached"
},
"updatedAt": "2026-03-20T14:00:00Z"
}
]
}
The following example shows how an enterprise uses collections to
organize a large number of artifacts into browsable categories. Each
collection points to a separate AI Catalog document:
{
"specVersion": "1.0",
"host": {
"displayName": "Acme Enterprise AI",
"identifier": "did:web:acme-corp.com"
},
"entries": [
{
"identifier": "urn:acme:agent:assistant",
"displayName": "Acme Corporate Assistant",
"version": "3.0.0",
"mediaType": "application/a2a-agent-card+json",
"url": "https://api.acme-corp.com/agents/assistant.json",
"description": "General-purpose corporate assistant agent."
}
],
"collections": [
{
"displayName": "Finance Services",
"url": "https://acme-corp.com/catalogs/finance.json",
"description": "Financial agents, MCP servers, and datasets.",
"tags": ["finance", "trading", "compliance"]
},
{
"displayName": "Engineering Tools",
"url": "https://acme-corp.com/catalogs/engineering.json",
"description": "CI/CD agents, code review tools, and DevOps servers.",
"tags": ["engineering", "devops", "ci-cd"]
},
{
"displayName": "ML Models",
"url": "https://acme-corp.com/catalogs/ml-models.json",
"description": "Model cards and inference endpoints.",
"tags": ["ml", "models", "inference"]
}
]
}
A catalog MAY contain both entries and collections. In this
example, the corporate assistant agent is listed directly while
department-specific artifacts are organized into child catalogs.
An AI Catalog entry for a Claude Code plugin (per the Claude Plugins marketplace):
{
"identifier": "urn:claude-plugin:endorlabs:ai-plugins",
"displayName": "ai-plugins",
"mediaType": "application/vnd.anthropic.claude-plugin+json",
"url": "https://github.com/endorlabs/ai-plugins.git",
"description": "Set up endorctl and use Endor Labs to scan, prioritize, and fix security risks across your software supply chain",
"tags": ["security", "supply-chain"],
"publisher": {
"identifier": "did:web:endorlabs.com",
"displayName": "Endor Labs"
},
"trustManifest": {
"identity": "urn:claude-plugin:endorlabs:ai-plugins",
"identityType": "did",
"attestations": [
{
"type": "publisher-identity",
"uri": "https://trust.endorlabs.com/certs/publisher.jwt",
"mediaType": "application/jwt",
"description": "Verifies did:web:endorlabs.com as publisher"
}
],
"provenance": [
{
"relation": "publishedFrom",
"sourceId": "https://github.com/endorlabs/ai-plugins",
"sourceDigest": "sha1:a0f1d5632b6f9e6c26eaa9806f5d8d454ca5b06f"
}
]
},
"metadata": {
"homepage": "https://www.endorlabs.com"
}
}
This appendix describes how AI Catalog documents can be distributed through OCI registries, enabling content-addressed storage, signing, and replication using existing container infrastructure.
The AI Catalog specification defines a logical format: a JSON
document with entries, displayName, mediaType, and trustManifest
fields that are immediately meaningful to anyone working with AI
artifacts. Authors write simple JSON. APIs serve simple JSON. Clients
consume simple JSON.
OCI provides a physical distribution layer: content-addressed
storage, cryptographic signing via Cosign/Notation, global replication
through registries, and referrer-based metadata association. These are
valuable infrastructure capabilities, but OCI's data model uses
container-oriented vocabulary (manifests, layers, config,
digest) that does not naturally describe a catalog of AI artifacts.
This specification treats OCI as one distribution option, not as the canonical data model. The logical AI Catalog format remains the authoring and consumption interface. Tooling bridges the two:
Authoring Distribution Consumption
───────── ──────────── ───────────
ai-catalog.json ──pack──► OCI Registry ──unpack──► ai-catalog.json
entries[] Index/Manifests entries[]
trustManifest Referrers trustManifest
This separation means:
/.well-known/ai-catalog.json or a registry API receive the logical
JSON format. They never need to parse OCI structures.The OCI image specification (v1.1+) supports arbitrary artifact types
through the artifactType field. The following table maps AI Catalog
concepts to their OCI physical equivalents:
| AI Catalog (Logical) | OCI (Physical) |
|---|---|
| AI Catalog document | OCI Image Index with artifactType: "application/ai-catalog+json" |
| Catalog Entry | OCI Image Manifest with artifactType set to the entry's mediaType |
Entry mediaType |
Manifest artifactType field |
| Entry artifact content | Manifest layers[0] blob (the protocol-specific document) |
| Entry metadata (name, tags, publisher) | Manifest config blob and/or annotations |
| Nested Catalog | Nested OCI Image Index referenced from the parent index |
| Trust Manifest | OCI Referrer artifact with subject pointing to the entry manifest |
| Trust Manifest attestations | Individual OCI Referrer artifacts per attestation |
| Signing | Cosign / Notation signatures as OCI Referrers |
Tooling converts an AI Catalog JSON document into OCI artifacts:
Each catalog entry becomes an OCI Image Manifest. The entry's
artifact content (A2A card, MCP manifest, skill definition) is
stored as a layers[0] blob. Common metadata (name, description,
publisher) is stored as the config blob or as annotations.
The catalog itself becomes an OCI Image Index whose manifests
array references the per-entry manifests by digest.
Trust Manifests become OCI Referrer artifacts attached to their
entry manifests via the subject field. Attestation documents
(JWTs, PDFs, SLSA provenance) become individual referrer layers.
Nested catalogs become nested OCI Image Indexes.
oci://registry.acme.com/ai-catalog:latest (Image Index)
├── manifest: finance-a2a-agent (Manifest)
│ ├── config: { name, description, publisher }
│ ├── layers[0]: a2a-card.json
│ └── referrer: trust-manifest (Referrer)
│ ├── config: trust-manifest.json
│ └── layers: [publisher.jwt, soc2.pdf]
├── manifest: finance-mcp-server (Manifest)
│ ├── config: { name, description }
│ └── layers[0]: mcp-server.json
└── index: finance-suite (Nested Index)
├── manifest: suite-a2a-agent
└── manifest: suite-mcp-server
Tooling converts OCI artifacts back to an AI Catalog JSON document:
config blob
(entry metadata) and layers[0] blob (artifact content).entries[] and
trustManifest fields.The result is a standard application/ai-catalog+json document
indistinguishable from one authored by hand.
The following shows the OCI physical representation of an AI Catalog containing two entries. Note that this is generated by tooling, not authored by hand:
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"artifactType": "application/ai-catalog+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:aaa111...",
"size": 1024,
"artifactType": "application/a2a-agent-card+json",
"annotations": {
"ai-catalog.identifier": "urn:acme:agent:finance-a2a",
"ai-catalog.displayName": "Acme Finance A2A Agent"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:bbb222...",
"size": 512,
"artifactType": "application/mcp-server+json",
"annotations": {
"ai-catalog.identifier": "urn:acme:server:finance-mcp",
"ai-catalog.displayName": "Acme Finance MCP Server"
}
}
],
"annotations": {
"ai-catalog.specVersion": "1.0",
"ai-catalog.host.displayName": "Acme Services Inc."
}
}
Because OCI distribution uses content-addressed digests, signing is handled by existing OCI tooling rather than embedded signature fields:
# Sign an entry manifest
cosign sign registry.example.com/ai/finance-a2a@sha256:aaa111...
# Verify
cosign verify registry.example.com/ai/finance-a2a@sha256:aaa111...
# Attach SLSA provenance
cosign attest --predicate provenance.json --type slsaprovenance \
registry.example.com/ai/finance-a2a@sha256:aaa111...
These signatures and attestations are discoverable via the OCI Referrers API and can be mapped back to Trust Manifest attestation objects during unpacking.
Some proposals (such as the AAIF AI Card OCI schema) take an OCI-native approach where the OCI Image Manifest is the data model. In that model, the AI Card is an OCI Manifest, protocol cards are OCI layers, and the catalog is an OCI Image Index consumed directly.
This specification takes a different position: the logical JSON format is the primary interface, and OCI is a distribution substrate. The tradeoffs are:
| Concern | Logical-first (this spec) | OCI-native |
|---|---|---|
| Authoring | Write simple JSON with domain vocabulary | Write JSON conforming to OCI Manifest schema |
| Vocabulary | entries, displayName, mediaType, trustManifest |
manifests, layers, config, annotations |
| Minimum viable serving | Static JSON file at any URL (optionally well-known) | OCI registry or static OCI layout |
| Signing | Detached JWS in logical format; Cosign/Notation in OCI | Cosign/Notation only |
| Content integrity | Optional digests in Trust Manifest | Guaranteed by OCI content-addressing |
| Ecosystem compatibility | Any HTTP server, any registry, any CDN | OCI-compliant registries |
| Adoption barrier | Low — familiar JSON | Higher — requires OCI familiarity |
Both approaches can coexist. A tooling bridge converts between them losslessly, allowing simple consumers to work with the logical format while infrastructure-oriented deployments leverage OCI distribution.
This appendix describes how the MCP Registry server.json format
(see modelcontextprotocol/registry)
relates to AI Catalog, enabling MCP servers to be discovered alongside
other AI artifacts through a unified catalog.
The MCP Registry defines a server.json format for describing MCP
servers. Each server.json document captures everything needed to
install, configure, and connect to a single MCP server: package
coordinates (npm, PyPI, NuGet, OCI), remote endpoints (streamable-http,
SSE), transport configuration, environment variables, and CLI arguments.
In AI Catalog terms, a server.json document is the artifact
content — the native metadata that a Catalog Entry references. The
AI Catalog does not duplicate or redefine server.json fields.
Instead, it provides the discovery envelope and trust layer that
server.json does not address.
MCP server.json |
AI Catalog Equivalent |
|---|---|
server.json document (whole file) |
Artifact content via entry url or inline |
name (reverse-DNS identifier) |
Entry identifier (mapped to URI form) |
title |
Entry displayName |
description |
Entry description |
version |
Entry version |
repository |
Entry metadata.repository |
packages[] (npm, pypi, nuget, oci) |
Inside the artifact — not surfaced in catalog |
remotes[] (streamable-http, sse) |
Inside the artifact — not surfaced in catalog |
environmentVariables[] |
Inside the artifact — not surfaced in catalog |
_meta |
Entry metadata for catalog-level hints; otherwise stays in artifact |
| (not in server.json) | Entry publisher |
| (not in server.json) | Entry trustManifest (identity, attestations, provenance) |
| (not in server.json) | Entry tags for cross-artifact discovery |
| MCP Registry (centralized service) | AI Catalog (decentralized, any URL) |
The server.json format and AI Catalog address different concerns:
This separation means the AI Catalog entry is thin — it points at the
server.json and adds only what server.json lacks: publisher
identity, trust verification, and cross-ecosystem discoverability.
An MCP server described by a server.json maps to a Catalog Entry
with mediaType set to application/mcp-server+json:
{
"identifier": "urn:mcp:io.modelcontextprotocol.anonymous/brave-search",
"displayName": "Brave Search",
"version": "1.0.2",
"mediaType": "application/mcp-server+json",
"url": "https://registry.modelcontextprotocol.io/servers/brave-search/server.json",
"description": "MCP server for Brave Search API integration",
"tags": ["search", "brave", "web"],
"publisher": {
"identifier": "did:web:modelcontextprotocol.io",
"displayName": "Model Context Protocol"
},
"trustManifest": {
"identity": "urn:mcp:io.modelcontextprotocol.anonymous/brave-search",
"attestations": [
{
"type": "publisher-identity",
"uri": "https://registry.modelcontextprotocol.io/certs/publisher.jwt",
"mediaType": "application/jwt",
"description": "Verifies did:web:modelcontextprotocol.io as publisher"
}
],
"provenance": [
{
"relation": "publishedFrom",
"sourceId": "https://github.com/modelcontextprotocol/servers",
"registryUri": "https://registry.npmjs.org"
}
]
},
"metadata": {
"repository": "https://github.com/modelcontextprotocol/servers"
},
"updatedAt": "2026-03-15T10:00:00Z"
}
The url points to the complete server.json. A client fetches the
catalog entry for discovery and trust evaluation, then retrieves the
server.json for operational details (packages, transports, env vars).
The MCP Registry — a centralized index of MCP servers — can be
represented as an AI Catalog. This enables clients that understand
application/ai-catalog+json to discover MCP servers alongside A2A
agents, skills, and other artifacts:
{
"specVersion": "1.0",
"host": {
"displayName": "MCP Server Registry",
"identifier": "did:web:modelcontextprotocol.io",
"documentationUrl": "https://modelcontextprotocol.io/docs"
},
"entries": [
{
"identifier": "urn:mcp:io.modelcontextprotocol.anonymous/brave-search",
"displayName": "Brave Search",
"version": "1.0.2",
"mediaType": "application/mcp-server+json",
"url": "https://registry.modelcontextprotocol.io/servers/brave-search/server.json",
"description": "MCP server for Brave Search API integration",
"tags": ["search", "brave"]
},
{
"identifier": "urn:mcp:io.github.modelcontextprotocol/filesystem",
"displayName": "Filesystem",
"version": "1.0.2",
"mediaType": "application/mcp-server+json",
"url": "https://registry.modelcontextprotocol.io/servers/filesystem/server.json",
"description": "MCP server for filesystem operations",
"tags": ["filesystem", "files"]
},
{
"identifier": "urn:mcp:io.github.example/weather-mcp",
"displayName": "Weather",
"version": "0.5.0",
"mediaType": "application/mcp-server+json",
"url": "https://registry.modelcontextprotocol.io/servers/weather/server.json",
"description": "Python MCP server for weather data access",
"tags": ["weather", "python"],
"publisher": {
"identifier": "did:web:example.github.io",
"displayName": "Example Corp"
}
}
]
}
The MCP Registry is a centralized service. AI Catalog enables
decentralized discovery: any domain can publish its MCP servers at
/.well-known/ai-catalog.json without registering with a central
authority.
A vendor hosting its own MCP servers can publish:
https://api.acme-corp.com/.well-known/ai-catalog.json
Clients and crawlers discover the catalog via the well-known URL,
find entries with mediaType: "application/mcp-server+json", and
fetch the server.json documents for operational details.
The centralized MCP Registry and decentralized AI Catalogs are complementary. The registry can serve an AI Catalog as its response format, while individual domains publish their own catalogs for direct discovery.
The server.json format has no trust or identity layer. AI Catalog
fills this gap:
server.json.MCP Server Cards
(SEP-1649)
define a static discovery document for individual HTTP-based MCP
servers at /.well-known/mcp/server-card.json. A Server Card mirrors
the MCP initialization handshake response: it carries the server's
name, version, transport configuration, capabilities, authentication
requirements, and optionally the full list of tools, resources, and
prompts.
AI Catalog and MCP Server Cards address different layers of discovery:
The two mechanisms layer naturally. An AI Catalog entry for an MCP server can reference the Server Card as its artifact content:
{
"identifier": "urn:mcp:example.com:finance-server",
"displayName": "Acme Finance MCP Server",
"mediaType": "application/mcp-server+json",
"url": "https://api.acme-corp.com/.well-known/mcp/server-card.json",
"description": "MCP server for financial data and trading tools",
"tags": ["finance", "mcp"],
"publisher": {
"identifier": "did:web:acme-corp.com",
"displayName": "Acme Financial Corp"
},
"trustManifest": {
"identity": "urn:mcp:example.com:finance-server",
"attestations": [
{
"type": "publisher-identity",
"uri": "https://trust.acme-corp.com/certs/publisher.jwt",
"mediaType": "application/jwt"
},
{
"type": "SOC2-Type2",
"uri": "https://trust.acme-corp.com/reports/soc2.pdf",
"mediaType": "application/pdf",
"digest": "sha256:a1b2c3d4e5f6"
}
]
}
}
A client discovering MCP servers follows this flow:
/.well-known/ai-catalog.json to discover all artifacts on
a domain (MCP servers, A2A agents, plugins, etc.).mediaType to find MCP servers.url for operational details
(transport, capabilities, tools, authentication).This separation ensures that AI Catalog provides the trust and cross-ecosystem indexing layer, while the MCP Server Card provides the protocol-specific operational details. A domain with multiple MCP servers publishes one AI Catalog listing all of them, with each entry pointing to its respective Server Card.
This appendix describes how the Anthropic Claude Code Plugins marketplace format (see claude-plugins-official) maps to AI Catalog, enabling Claude Code plugins to be discovered, indexed, and distributed through a unified catalog alongside other AI artifacts.
The Claude Code Plugins marketplace is defined by a marketplace.json
file that lists available plugins. Each plugin is a directory containing
a .claude-plugin/plugin.json metadata file and optional components:
MCP server configurations (.mcp.json), slash commands (commands/),
agent definitions (agents/), and skill definitions (skills/).
marketplace.json # Top-level plugin directory
plugins/
example-plugin/
.claude-plugin/
plugin.json # Plugin metadata (name, description, author)
.mcp.json # MCP server config (optional)
commands/ # Slash commands (optional)
agents/ # Agent definitions (optional)
skills/ # Skill definitions (optional)
README.md
| Claude Plugins Marketplace | AI Catalog Equivalent |
|---|---|
marketplace.json (whole file) |
AI Catalog document (top-level) |
Marketplace name |
Catalog host.displayName |
Marketplace description |
Catalog metadata.description |
Marketplace owner |
Catalog host (with identifier derived from owner) |
plugins[] array |
Catalog entries[] array |
Plugin name |
Entry displayName and identifier (derived as URN) |
Plugin description |
Entry description |
Plugin category |
Entry tags[] (first tag) |
Plugin tags |
Entry tags[] (merged with category) |
Plugin author |
Entry publisher |
Plugin source (url, git-subdir, or path) |
Entry url (pointing to the plugin repository) |
Plugin source.sha |
Entry trustManifest.provenance[].sourceDigest |
Plugin homepage |
Entry metadata.homepage |
Plugin .claude-plugin/plugin.json |
The artifact content (referenced via url) |
| (not in marketplace) | Entry trustManifest (identity, attestations) |
| (not in marketplace) | Entry mediaType |
| Centralized marketplace repo | AI Catalog (decentralized, any URL) |
The marketplace supports three source types for plugins. Each maps differently to AI Catalog entry fields:
{"source": "url", "url": "https://github.com/org/repo.git", "sha": "..."}
maps to entry url pointing at the repository, with sha captured
as provenance digest.{"source": "git-subdir", "url": "org/repo", "path": "plugins/name", "ref": "main"}
maps to entry url constructed from the repository, path, and ref."./plugins/name" or "./external_plugins/name" maps to entry url
pointing at the known repository location for the plugin directory.The marketplace.json from
claude-plugins-official
maps to an AI Catalog where each plugin is an entry:
{
"specVersion": "1.0",
"host": {
"displayName": "Claude Code Plugins Directory",
"identifier": "did:web:anthropic.com",
"documentationUrl": "https://code.claude.com/docs/en/plugins"
},
"entries": [
{
"identifier": "urn:claude-plugin:anthropic:agent-sdk-dev",
"displayName": "agent-sdk-dev",
"mediaType": "application/vnd.anthropic.claude-plugin+json",
"url": "https://github.com/anthropics/claude-plugins-official/tree/main/plugins/agent-sdk-dev",
"description": "Development kit for working with the Claude Agent SDK",
"tags": ["development"],
"publisher": {
"identifier": "did:web:anthropic.com",
"displayName": "Anthropic"
},
"metadata": {
"homepage": "https://github.com/anthropics/claude-plugins-public/tree/main/plugins/agent-sdk-dev"
}
},
{
"identifier": "urn:claude-plugin:adspirer:ads-agent",
"displayName": "adspirer-ads-agent",
"mediaType": "application/vnd.anthropic.claude-plugin+json",
"url": "https://github.com/amekala/adspirer-mcp-plugin.git",
"description": "Cross-platform ad management for Google Ads, Meta Ads, TikTok Ads, and LinkedIn Ads.",
"tags": ["productivity", "ads"],
"metadata": {
"homepage": "https://www.adspirer.com"
},
"trustManifest": {
"identity": "urn:claude-plugin:adspirer:ads-agent",
"provenance": [
{
"relation": "publishedFrom",
"sourceId": "https://github.com/amekala/adspirer-mcp-plugin",
"sourceDigest": "sha1:aa70dbdbbbb843e94a794c10c2b13f5dd66b5e40"
}
]
}
},
{
"identifier": "urn:claude-plugin:aikido:security",
"displayName": "aikido",
"mediaType": "application/vnd.anthropic.claude-plugin+json",
"url": "https://github.com/AikidoSec/aikido-claude-plugin.git",
"description": "Aikido Security scanning — SAST, secrets, and IaC vulnerability detection.",
"tags": ["security"],
"publisher": {
"identifier": "did:web:aikido.dev",
"displayName": "Aikido Security"
},
"trustManifest": {
"identity": "urn:claude-plugin:aikido:security",
"provenance": [
{
"relation": "publishedFrom",
"sourceId": "https://github.com/AikidoSec/aikido-claude-plugin",
"sourceDigest": "sha1:d7fa8b8e192680d9a26c1a5dcaead7cf5cdb7139"
}
]
}
}
]
}
A plugin that bundles multiple components (MCP servers, skills, commands, agents) naturally maps to a nested AI Catalog. This mirrors the plugin directory structure where a single plugin contains multiple artifact types:
{
"identifier": "urn:claude-plugin:anthropic:example-plugin",
"displayName": "example-plugin",
"mediaType": "application/ai-catalog+json",
"description": "Comprehensive plugin with commands, agents, skills, and MCP servers",
"tags": ["development", "bundle"],
"publisher": {
"identifier": "did:web:anthropic.com",
"displayName": "Anthropic"
},
"inline": {
"specVersion": "1.0",
"entries": [
{
"identifier": "urn:claude-plugin:anthropic:example-plugin:mcp",
"displayName": "Example Plugin MCP Server",
"mediaType": "application/mcp-server+json",
"url": "https://github.com/anthropics/claude-plugins-official/tree/main/plugins/example-plugin/.mcp.json"
},
{
"identifier": "urn:claude-plugin:anthropic:example-plugin:skills",
"displayName": "Example Plugin Skills",
"mediaType": "application/vnd.agentskills.skill+md",
"url": "https://github.com/anthropics/claude-plugins-official/tree/main/plugins/example-plugin/skills"
}
]
}
}
The marketplace.json format is a lightweight directory focused on
listing available plugins. AI Catalog extends this with:
Trust and identity: The marketplace has no signing, attestation, or publisher verification. Trust Manifests provide verifiable publisher identity and compliance metadata.
Source integrity: The marketplace includes optional sha fields
on source references. AI Catalog formalizes this as provenance links
with typed relations and cryptographic digests.
Cross-ecosystem discovery: Plugins become discoverable alongside
MCP servers, A2A agents, and other artifacts through the standard
/.well-known/ai-catalog.json convention — not only within Claude
Code's /plugin system.
Media type identification: The marketplace does not type its
plugins. AI Catalog assigns application/vnd.anthropic.claude-plugin+json
enabling clients to filter and route by artifact type.
Composability: Plugin bundles that combine skills, MCP servers, and commands can be represented as nested catalogs, making the internal structure of a plugin package explicit and independently addressable.
Decentralized publishing: Any domain can publish Claude Code plugins via AI Catalog without submitting to the centralized marketplace repository.
This specification was developed through collaboration among members of the A2A and MCP protocol communities under the governance of the Linux Foundation.