spec: AI card and AI catalog draft proposal#4
spec: AI card and AI catalog draft proposal#4mindpower wants to merge 24 commits intoAgent-Card:mainfrom
Conversation
…lds, service specific metadata are defined as extensions
2688feb to
5f7a399
Compare
…-catalog draft definition, updated examples
|
@ToddSegal @dsp-ant Please review and let me know if you have any concerns or questions :-) |
|
@mindpower thanks for writing this up! I have a question: Will there then still be a standalone MCP Server Card (related modelcontextprotocol/modelcontextprotocol#1649) or would we then always use the AI Card to describe an MCP Server in full? With A2A it seems to work differently, because A2A already has a standalone A2A Card format, which may best be linked and not repeated? |
type/ai-card-example.md
Outdated
| "scheme": "bearer", | ||
| "bearerFormat": "JWT" | ||
| }, | ||
| "protocolSpecific": { |
There was a problem hiding this comment.
Will this then be identical to MCP Server Card or replace it?
Some information are now on the non protocol specific side.
If there is still an MCP Server card, could it be linked instead?
There was a problem hiding this comment.
The auth part will be identical to the MCP card. But we can further discuss the auth for A2A and MCP and other protocol. If it's hard to merge, we can keep them separately as protocol specific.
If there is still an MCP Server card, could it be linked instead?
The MCP (and also A2A) protocol specific definition are not part of the core ai card and should be defined by each spec (A2A, or MCP). But ai-card.json should include all the data, like the following, with service declare the service (A2A, MCP) specific properties:
+ <common ai-card fields>
+ <service interfaces>
+ <service 1>
+ <service 2>
+ <service 3>
type/ai-card-example.md
Outdated
| "bearerFormat": "JWT" | ||
| }, | ||
| "protocolSpecific": { | ||
| "protocolVersion": "2025-06-18", |
There was a problem hiding this comment.
Shouldn't this be an array, to match how it works with MCP Server.json from registry spec?
There was a problem hiding this comment.
Which specific MCP server field do you think need to be an array here?
The services here is an array which will supports multiple service interfaces. Also the ai catalog will support multiple agent declaration as well.
There was a problem hiding this comment.
ProtocolVersions. It's supportedProtocolVersions in the MCP Registry spec I think.
Reason is that one server can (and has to) support multiple protocol versions at the same time to keep compatibility with clients.
There was a problem hiding this comment.
I see. Thanks @Fannon for the clarification. Yes we can update the example to supportedProtocolVersions. Here is just to give an example of the protocol specification. It's up to MCP to decide any required fields.
|
Thanks @Fannon for the review. Please see the reply above. Regarding the standalone MCP server card, yes that will be defined separately (not the core ai card spec), but the data will be included in the ai-card.json.
|
It would be my expectation that we will remove elements from the A2A card that appear in the common area of the AI Card. |
|
I may not have fully grasped the exact intent of this project yet, but based on the README, wouldn't the |
type/src/ai-card.ts
Outdated
| /** | ||
| * A direct URL to the agent's logo image. | ||
| */ | ||
| logoUrl?: string; |
There was a problem hiding this comment.
It is not uncommon to have a requirement for multiple logo/icons. One for list views and a larger one for detail pages. Not sure how flexible we would want to be.
There was a problem hiding this comment.
Thanks @darrelmiller !
To keep the V1 spec lightweight and easy to parse, it might be better to stick with a single logoUrl string for now? If we find that distinct aspect ratios or multiple formats are a blocker for adoption, we can upgrade this field to support the full W3C ImageResource array structure in a future version like following:
// --8<-- [start:ImageResource]
/**
* Defines an image resource (icon/logo) for the agent.
* Based on the W3C ImageResource specification used in Web App Manifests.
*/
export interface ImageResource {
/**
* The source of the image.
* * SECURITY NOTE: We strongly recommend using **Data URLs** (RFC 2397)
* (e.g., "data:image/png;base64,...") to embed the image binary directly.
*/
src: string;
/**
* A hint as to the media type of the image.
* e.g., "image/png", "image/svg+xml"
*/
type?: string;
/**
* A string containing space-separated image dimensions.
* e.g., "144x144", "512x512", "any" (for SVG)
*/
sizes?: string;
/**
* The purpose of the image, for context.
* e.g., "monochrome", "maskable", "any"
*/
purpose?: string;
}
/**
* A list of icons/logos for the agent.
* Replaces the legacy 'logoUrl' field to support multiple sizes and Data URIs.
*/
logoIcons?: ImageResource[];
type/src/ai-card.ts
Outdated
| /** | ||
| * The version of the AI Card specification itself. | ||
| */ | ||
| specVersion: string; |
There was a problem hiding this comment.
If we are going to make $schema required, is there also a need for a specVersion? Is it likely that one would change but the other would not?
There was a problem hiding this comment.
That's a great question. While they seem redundant, they serve distinct needs:
$schemais for automated validators. It points to the definition file location. Typically, these URLs are 'pinned' to a major version (e.g.,.../v1/schema.json) to avoid breaking clients on minor, non-breaking updates.specVersionis for client logic. It allows a client to easily check for specific feature support (e.g.,if version >= '1.2') without having to regex parse a URL string.- Decoupling. Keeping
specVersionseparates the logical version of the standard from the physical hosting location of the schema file, making the system more robust over time.
For example, the MCP card proposal(modelcontextprotocol/modelcontextprotocol#1649) also includes both a schema and a version field (protocolVersion) or (protocolVersions) as discussed above, acknowledging that clients need an easy way to check for feature matching without parsing schema URLs:
type/src/ai-card.ts
Outdated
| /** | ||
| * The primary verifiable ID for the agent (e.g., DID). | ||
| */ | ||
| id: string; |
There was a problem hiding this comment.
Is it a requirement that this is "verifiable" or would that just be a recommendation?
There was a problem hiding this comment.
That is a great clarification. The schema only requires id to be a string, so strictly speaking, it is a recommendation for the format.
However, we strongly recommend using a verifiable format (like did, spiffe) rather than a simple UUID or name. While a simple string is valid JSON, it prevents the agent from participating in high-trust workflows (like automated compliance verification) because there is no mechanism to prove ownership of a generic string.
Updated the spec for more clarification.
type/src/ai-card.ts
Outdated
| /** | ||
| * The identity string itself. | ||
| */ | ||
| id: string; |
There was a problem hiding this comment.
What is the difference between this id and the id at the root?
There was a problem hiding this comment.
Good catch on the potential redundancy. Here is the distinction:
- Root
id: This is the canonical Agent ID (did, spiffe, etc) used for discovery, indexing, and database keys. trust.identity.id: This is the Verification Subject. While it must match the Rootid, including it explicitly in theIdentityobject ensures that the security context is self-contained. This prevents 'context confusion' where a detached signature might be applied to the wrong parent object during parsing.- Also,
publisher.id: This is distinct. It identifies the Organization (e.g., Acme Corp) that owns the agent, whereas the Rootididentifies the specific Agent instance (e.g., Finance Bot 3000).
I will add comments to the schema to explicitly define these relationships and the requirement that Root id and trust.identity.id must match.
type/src/ai-card.ts
Outdated
| * Add here if we want to standardize authentication across all services. | ||
| * Otherwise, each protocol would define its own. | ||
| */ | ||
| authentication: any; |
There was a problem hiding this comment.
I think it is going to be challenging to get alignment on authentication mechanisms across all protocols. Unless we assume that everything is going to use HTTP based auth. Even then it is going to be hard.
There was a problem hiding this comment.
That is a very pragmatic point. You are right. Getting 100% alignment across all possible future protocols (especially non-HTTP ones) is likely impossible and brittle.
To address this, I propose we treat the top-level authentication field as a recommended standard specifically for HTTP-based interactions (like A2A and MCP), based on the OpenAPI specification.
- For standard HTTP protocols: We recommend declaring auth using same openAPI spec here. This allows generic clients (like a registry dashboard) to handle common flows like OAuth2 or API Keys without needing deep knowledge of every specific protocol.
- For non-standard/exotic protocols: They can simply omit this field and define their bespoke authentication requirements entirely within their
protocolSpecificpayload.
This gives us the benefit of standardization for the vast majority of web-based agents without constraining innovation for other transports. I am also OK that we just remove this for initial version if that make things simple.
There was a problem hiding this comment.
That's am interesting proposal. We will probably need some words to clarify what should happen if there is a contradiction between the top level authentication property and the protocol specific auth details.
@ognis1205 Thanks for the follow-up! You hit the nail on the head. I think the term 'server' is doing a lot of heavy lifting in the current README, covering both the Agent itself and the Host infrastructure. That dual meaning effectively created the ambiguity here. To clarify the specific scope: 1. The Terminology Ambiguity 2. The Distinct Scopes
3. Naming & Repo Action Plan:
Does that distinction make sense? |
@OR13 Thanks for the feedback. You raise a valid point about scope! We don't want to inadvertently mandate a complex PKI or specific DID method in the base schema PR. I agree we should defer the normative security implementation details to a later PR or a specific "Security Profile" document. To address your concerns and unblock the structural definition:
The goal is to reserve the "slots" in the JSON for identity and security (so the schema is stable) without forcing a specific complex deployment model in V1. Does that decoupling sound like the right approach? |
…not provide the complex id verification and compliance trust field
|
Updated the pr based recent discussions. Here is the latest ai card in CDDL format: ; ============================================================================
; AI Card Specification (v1)
; A unified metadata format for AI Agents
; ============================================================================
AICard = {
$schema: text, ; URI to the JSON schema (e.g. "https://...")
specVersion: text, ; Major.Minor version (e.g. "1.0")
; --- Identity (Subject) ---
id: text, ; The Primary Key / Subject of this card, Globally Unique URI (per RFC 3986), (DID, SPIFFE, or URL)
? identityType: text, ; Type hint (e.g. "did", "spiffe"). Optional if clear from ID.
; --- Metadata ---
name: text, ; Human-readable name for the agent
description: text, ; Short description of the agent's purpose
? logoUrl: text, ; URL to logo. Data URL (RFC 2397) recommended for privacy
? tags: [* text], ; List of keywords to aid in discovery
? maturity: MaturityLevel, ; Lifecycle stage of the agent
; --- Ownership & Trust ---
publisher: Publisher, ; Information about the entity that owns this agent
? trust: Trust, ; Security and compliance proofs
? signature: text, ; Detached JWS signing the card content
; --- Protocols ---
; Map of supported protocols (e.g. "a2a" => Service, "mcp" => Service)
services: { * ServiceType => BaseService },
; --- Housekeeping ---
createdAt: tdate, ; ISO 8601 Date when the agent was created
updatedAt: tdate, ; ISO 8601 Date when this card was last modified
? metadata: { * text => any } ; Open slot for custom/non-standard metadata
}
; Enum for maturity
MaturityLevel = "preview" / "stable" / "deprecated"
; Service type choices (Standard + Custom)
ServiceType = "mcp" / "a2a" / text
; --- Core Components ---
Publisher = {
id: text, ; Verifiable ID of the publisher organization
? identityType: text, ; Type hint (e.g. "did", "dns")
name: text, ; Human-readable name of the publisher
? attestation: Attestation ; Proof of the publisher's identity
}
Trust = {
; Identity is now implicit (matches Root id)
? attestations: [* Attestation], ; List of compliance credentials (SOC2, HIPAA, etc.)
? privacyPolicyUrl: text, ; URL to the privacy policy
? termsOfServiceUrl: text ; URL to the terms of service
}
Attestation = {
type: text, ; Type of proof (e.g. "SOC2-Type2", "HIPAA-Audit")
; Verifiable credentials (High-Trust)
? credentialUrl: text, ; Remote URL to a signed credential (e.g. JWT/PDF)
? credentialValue: text ; Embedded base64-encoded credential (e.g. JWT)
}
; --- Interaction Services ---
BaseService = {
type: ServiceType, ; Protocol ID (matches key in services map)
? name: text, ; Human-readable label (e.g. "Primary Interface")
; The "Black Box" for protocol-specific data
; Endpoints, Auth, and Skills are defined INSIDE here by the protocol spec.
protocolSpecific: { * text => any }
} |
|
Thanks @mindpower , really appreciate the clarification and the discussion! The distinction you described between Regarding the terminology, though:
I think using So it would be great if you could take that into account as well. And again, I fully support clearly documenting the two scopes:
These distinctions will make the spec much easier for implementers to follow. |
|
@mindpower regarding: #4 (comment) IMO Yes. If the goal is secure the card contents, consider https://a2a-protocol.org/latest/specification/#447-agentcardsignature If the goal is to advertise other signatures related to the card, consider some simple inline and by reference example, using media types and URLs. You don't really want a "card verifier" to end up having to implement a bunch of different crypto to understand cards, so its better to recommend some mandatory to support basics, and then leave the option for non standard / less well used stuff to be used by the folks that want to use it. Consider just including URI, Media Type, Size, and Hash, instead of mandating the format of related security assertions, see: |
|
Regarding: #4 (comment) Thanks @ognis1205 ! That is an excellent nuance. You are absolutely right that 'Agent' is too narrow, as it implies autonomy that a simple MCP tool server might not have. Using 'AI Service' or 'AI Protocol Server' as the umbrella term is much more precise. It correctly encompasses:
I will adopt the suggested 'AI Protocol Server' in the definitions to ensure we don't exclude tool-centric implementations. I'll proceed with updating the README to reflect: (Please see: #8)
Thanks again for helping clarify these definitions. It will make the spec much more robust for implementers. |
|
Thanks @OR13! Regarding: #4 (comment) This is excellent advice. I strongly agree that we want to avoid forcing every 'card verifier' to implement a kitchen sink of crypto libraries just to parse the document. 1. Card Integrity ( 2. External Trust ( Instead of defining specific fields like Attestation = {
type: text, ; The semantic type (e.g. "SOC2-Type2", "HIPAA-Audit")
uri: text, ; Location of the credential. Supports both:
; - Remote: "https://trust.example.com/report.pdf"
; - Inline data: "data:application/jwt;base64,eyJ..."
mediaType: text, ; The format (e.g. "application/jwt", "application/pdf")
; Tells the verifier which parser to use.
? digest: text ; Optional integrity check (e.g. "sha256:...")
; Critical for remote URLs to ensure content hasn't changed.
? size: uint, ; Size in bytes.
; Helps clients decide whether to download.
? description: text ; Human-readable label (e.g. "2025 Security Audit")}
}I can see the benefit that this allows:
I will update the spec to reflect this cleaner 'Reference' model. |
ognis1205
left a comment
There was a problem hiding this comment.
I focused my review primarily on the boundary between AICatalog and AICard and how their responsibilities relate. I hope the discussion helps clarify the intended role of the AICard in particular, since making that boundary explicit will strengthen the overall design.
type/ai-card-cddl.md
Outdated
| ```ini | ||
| ; ============================================================================ | ||
| ; AI Card Specification (v1) | ||
| ; A unified metadata format for AI Agents |
There was a problem hiding this comment.
As we discussed previously, I'm wondering if we should update the wording from "AI Agents" to "AI Protocol Servers."
What do you think?
There was a problem hiding this comment.
Please see the other reply below.
type/ai-card-cddl.md
Outdated
|
|
||
| ; --- Protocols --- | ||
| ; Map of supported protocols (e.g. "a2a" => Service, "mcp" => Service) | ||
| services: { * ServiceType => BaseService }, |
There was a problem hiding this comment.
I would like to add one point that has been on my mind regarding the services field and the conceptual model of the AICard.
The A2A specification and the current MCP card proposal/draft both describe their cards as a "business card for a AI protocol server", meaning a protocol-specific identity document.
But if an AICard contains multiple protocol entries under services (e.g., "a2a", "mcp", etc.), then the card no longer represents the business card of anything in particular, I guess. It effectively becomes a meta-card, a directory or an index that aggregates protocol-specific service descriptors.
This ambiguity is actually one of the reasons why I felt that what is proposed as the AICatalog in this PR is very close to what the AICard itself was implicitly trying to become. If a single card can represent multiple protocols, then in practice it behaves like a catalog rather than a protocol-scoped identity document. Even though, in this PR, each protocol is allowed to have only a single descriptor, the structural direction still points toward a catalog-like aggregation rather than a strictly scoped card.
To me, this raises an open design question:
- Should an
AICardremain a protocol-specific business card (1 protocol = 1 card)? - Or should the
AICardexplicitly become a meta-card, and theAICatalogcontain protocol-specific cards?
I think clarifying this distinction explicitly would help solidify the semantics of both AICard and AICatalog.
There was a problem hiding this comment.
These are excellent architectural questions. Here is how I see the scope of AICard.
Regarding the "meta-card" concern: I view the AICard as an Identity Document for a logical entity, rather than just a config file for a protocol.
The Analogy: Think of a human Business Card. It lists a Phone Number, an Email Address, and a Slack Handle.
- It supports "multiple protocols" (Voice, SMTP, Chat).
It does not become a "directory" or "phone book" because of this. It is still a single card describing one person.
The Benefit: By grouping A2A and MCP interfaces under one AICard, we allow Single Verification. A client verifies the Agent's DID once (checking the signature/compliance), and that trust automatically extends to all its interfaces (A2A and MCP). If we enforced "1 Protocol = 1 Card," we would fragment the identity, forcing clients to perform redundant trust checks for every single endpoint, which is brittle and computationally expensive.
There was a problem hiding this comment.
Thanks @mindpower ! I completely agree with both points:
Regarding the "meta-card" concern: I view the
AICardas an Identity Document for a logical entity, rather than just a config file for a protocol.
The Benefit: By grouping A2A and MCP interfaces under one AICard, we allow Single Verification.
I think the overall direction makes sense.
That said, I still feel we need to explore the question of what exactly this "logical entity" corresponds to in real deployments. For example, is an AIService always expected to expose exactly one MCP server or one A2A server? Or could a single AIService operate multiple MCP endpoints (e.g., one for tools and one for workflows) or multiple A2A servers (e.g., different domains or capabilities)?
If such patterns are valid, and I suspect they might be in production settings, then the mapping between the "single logical entity" and the underlying protocol servers becomes less clear. In that case, it would be important to clarify whether the AICard is representing:
- a single agent instance,
- a product-level service composed of multiple protocol servers, or
- a higher-level organizational identity grouping many protocol endpoints.
Here is a concrete example:
A company exposes an "AI Document Assistant" as one logical service. Internally, it runs
- two MCP servers (one for document-editing tools, one for knowledge-base queries),
- one A2A server for agent-to-agent orchestration,
all representing the same "AIService" to clients.
This doesn't seem far-fetched, but it would complicate assumptions about "one logical entity -> one server per protocol." So I agree with the single-verification direction, but I also believe we need a bit more clarity on the expected granularity of an AIService and how it maps to real-world multi-endpoint setups.
There was a problem hiding this comment.
Please see comments below (#4 (comment))
type/ai-catalog-cddl.md
Outdated
| $schema: text, ; URI to the JSON schema | ||
| specVersion: text, ; Version of the Catalog spec (e.g. "1.0.0") | ||
| host: HostInfo, ; Who runs this server/registry | ||
| agents: [* AICardEntry] ; The list of available agents |
There was a problem hiding this comment.
In earlier discussions, we noted that the term "agent" is specific to A2A, and does not cleanly apply to other protocols such as MCP, where the entity is a server, tool host, or protocol endpoint, but not necessarily an "agent."
Because the AICatalog is intended to be protocol-agnostic, naming the collection agents creates the wrong abstraction layer. This is arguably the place where a more neutral term like services fits better.
There was a problem hiding this comment.
I agree that 'Agent' is too narrow (too A2A-specific), but I also find 'AI Protocol Server' a bit clunky. It risks confusion with physical hosting infrastructure. I also thought of 'entries' but that felt too generic.
Counter-Proposal: 'AI Service' + 'Interfaces'
I propose we use 'AI Service' as the standard term for the logical entity. It naturally covers both Agents (active) and Tools (passive) without implying infrastructure.
To avoid the naming collision you mentioned (having a services list inside an AI Service), I propose renaming the protocol map in the AICard from services to interfaces.
This aligns well with A2A's existing supportedInterfaces concept and creates a very clean hierarchy::
-
AICatalog: Lists availableservices(The Entities/AI Services). -
AICard: Describes one
AI Service(The Identity). -
interfaces: Defines the A2A/MCP endpoints (The Connectivity).
I will update the README, Catalog, and Card specs to reflect this 'AI Service' terminology. Does this structure work for you?
There was a problem hiding this comment.
The points you raised are absolutely correct.
I agree that AI Service and interfaces are much better aligned with a protocol-agnostic design. Thank you for the thoughtful suggestion. I fully support adopting this terminology!
There was a problem hiding this comment.
I previously posted a short comment expressing support for AI Service and interfaces. After reflecting on it further, I'd like to expand that position with a few more detailed thoughts.
I'm thinking of using the following terminology:
- AICatalog -> services
- AICard -> interfaces (or possibly protocols, if that better captures the behavior/contract)
The goal is to keep the catalog focused on what is available, and the card focused on how to interact with it.
I'd be interested in your thoughts on whether "interfaces" or "protocols" is the better fit.
Here's why I believe interfaces for the AICard and services for the AICatalog map most cleanly to the conceptual model we're shaping.
### Why interfaces/protocols fits the AICard
The AICard is essentially the business card of a logical entity (the AIService). What it lists are the connectivity points:
- A2A endpoint
- MCP endpoint
- Endpoints for any other supported protocol
One additional point is the alignment with the A2A specification’s abstraction of AgentInterface
(https://a2a-protocol.org/latest/specification/#446-agentinterface).
In A2A, an interface represents a concrete connectivity surface for interacting with an agent, a strongly protocol-scoped endpoint definition. Structurally and semantically, this maps perfectly to what an AICard is supposed to describe:
These are all "surfaces through which the service can be interacted with," which aligns naturally with the term interfaces. So interfaces/protocls provides the right abstraction and keeps the meaning precise.
### Why services fits the AICatalog
There are two reasons this wording feels right:
- The catalog enumerates AIServices
- It aligns with established terminology
Framing the catalog as a directory of services fits naturally into that ecosystem.
I reviewed the PR again and realized that the terminology had already been updated to services and interfaces, sorry for missing that earlier. With that in mind, I'd like to propose considering protocols instead of interfaces.
The main reason is that, when looking at the abstraction defined in A2A (especially the AgentInterface in the spec), the term interface becomes a bit overloaded. What we are actually describing here feels closer to a communication or interaction protocol, rather than an API-shaped interface.
Would love to hear your thoughts on whether this framing makes sense.
There was a problem hiding this comment.
Thanks @ognis1205 . That's excellent feedback, and I completely agree. I was worrying that interface could be still confusing but was not able to come with the best name. The term protocols is more accurate, least ambiguous choice. It aligns perfectly with the keys of the map ("a2a", "mcp") and avoids the collision with the existing A2A AgentInterface and the TypeScript keyword interface.
Here is the final, consistent hierarchy this change establishes (hopefully!)
AICataloglists AI Services (The Entities).AICarddescribes one AI Service (The Identity).protocolsdefines the specific communication layers (The Connectivity/Doors).
I will make this final renaming (interfaces -> protocols) across the CDDL, JSON, and TypeScript definitions if the above looks good.
Thanks for spotting that necessary clarification!
There was a problem hiding this comment.
Thanks for adopting my suggestion about using the term protocols @mindpower ! I think this naming change moves the spec in a much clearer and more consistent direction. Overall, I believe the structure is evolving in a very good way.
At the same time, as I mentioned in
I still feel the logical unit represented by a single AICard (AI Service) remains a bit ambiguous. In particular, it may be worth discussing whether a single AI Service is expected to have multiple server infrastructures for the same protocol (e.g., multiple MCP or A2A endpoints under one card), and how the model should represent such cases.
There was a problem hiding this comment.
Thanks @ognis1205. You are right that real-world production AI services could be composed of multiple distributed endpoints (e.g., separate tool vs. workflow endpoints, or regional shards).
To handle this robustly, we can update the protocols map so the protocols values are Arrays (Protocol[]) rather than single objects.
The schema definition would be: protocols: { * ProtocolType => [* AIProtocol] }
This allows a single AICard (the Logical Service Identity) to expose multiple physical interfaces for the same protocol. This structure maintains the integrity of the Single Verification principle (verifying the card verifies all endpoints - I think this is the key here) while accommodating complex composite infrastructure.
There was a problem hiding this comment.
Thanks @mindpower ! This change makes sense to me.
Here's a possible naming refinement:
Since the value now represents the concrete information for each protocol, it might be clearer to rename:
AIProtocol->ProtocolDetail
If so, the key would naturally become:
ProtocolType->ProtocolName
This is just a naming suggestion; overall I agree with the direction of the change.
There was a problem hiding this comment.
Thanks for the suggestion!
ProtocolDetail: I like this rename for the object type. It clearly signals 'This object holds the details for one specific protocol binding.' I will adopt that.- Naming the
typefield: I prefer to keep the field inside the object astype(instead ofprotocolName).
- Reason:
typeis the standard convention for discriminators in JSON schemas. UsingprotocolNamemight get confused with the human-readablenamefield right next to it. - Illustration: Imagine the confusion if we had
protocolName(the enum) next toname(the label) in theProtocolDetailstructure below
// Map
protocols: Record<ProtocolType, ProtocolDetail[]>
// Object
interface ProtocolDetail {
type: string; // "a2a"
name?: string; // "Primary Interface"
protocolSpecific: ...
}- Human-Readable Labels: You raised a good point about how these look to users. Now I wonder how developer set the
namevalues inside the mapprotocolDetailfor each of theprotocolthey define.
-
For example, For the ai card called "Finance Agent", should the
namefor A2AprotocolDetailbe called as: "Finance Agent A2A Protocol"? this sounds very robotic. Similarly for MCP, should itsnamebe called"Finance Agent MCP Protocol", also too robotic -
We have a semantic conflict between the Technical Architecture (
Protocol) and the User Experience (Service/Interface). we (correctly) renamed the schema field toprotocolsto be technically precise, but that makes the English label feel awkward. -
Suggestion: The Human-Readable Name (
name) does not need to use the wordProtocolorService. It should describe the Function. -
Example:
"name": "Finance Agent Interface"or"name": "Finance Agent MCP workflow service" -
We can leave the
namefield flexible for developers to describe the function of that interface (e.g., 'Primary', 'Backup', 'Tools') rather than just repeating the protocol name.
There was a problem hiding this comment.
Thanks for the clarification, I'm aligned with this direction. Looks good to proceed with this change!
…gy, and simplify 'Attestation' to use Reference Pattern instead of specific credential fields
|
Just updated Also created PR #8 for the README change to clarify all the terminology, scopes, and architecture models. And updated the description above for this PR. |
…tocol interfaces in AI card
Thanks for pulling all of this together, appreciate the updates to both the specs and examples. |
…in AI Card specification, updated comparison.md
type/src/ai-catalog.ts
Outdated
| /** | ||
| * Information about the host/publisher of the entire catalog. | ||
| */ | ||
| host: HostInfo; |
There was a problem hiding this comment.
Can host be optional? I think many MCP use cases would not care to populate this, so not sure we want this to be a required field.
type/src/ai-catalog.ts
Outdated
| /** | ||
| * The full, absolute URL to this AI service's complete `ai-card.json` file. | ||
| */ | ||
| cardUrl: string; |
There was a problem hiding this comment.
Could we consider allowing pointing to an MCP Server Card (or A2A Agent Card) directly here?
This is probably tied to the uncertainty around "do we definitely want/need an envelope AI card format". If we were to adopt the shared extension approach @ToddSegal brought up in the first call, we wouldn't need the AI card intermediating here.
From my POV, for much of what MCP wants out of discovery:
- It would be sufficient to have a
.well-knownlocation whereai-catalog.jsoncan be found - We want a way to get from
ai-catalog.jsonto an instance of an MCP Server Card - So if this cardUrl can be an MCP Server Card (perhaps with an additional
protocolfield of some sort), I think that's likely to work for us, and we accomplish our shared goal of having a unified discovery layer.
This current model requires an extra hop, to go ai-catalog.json -> AI Card -> MCP Server Card. And the current proposal for AI Card has shapes/duplication of values we intend to (additionally?) store in MCP Server Card, and I'm not sure we'd want to combine governance of those fields to be in the critical path of discovery.
There was a problem hiding this comment.
Pushing for alignment on all of AI Card's current scope will be a long road, I think. For example, I think tags, maturity, logoUrl, etc all require discussion that we've discussed at length in various ways within the MCP ecosystem. And if we strip out all the controversial things that require alignment, I worry we end up with a very thin AI Card layer (in which case why not sidestep all that coordination and just link to MCP Server Cards / A2A Agent Cards directly here)?
There was a problem hiding this comment.
@tadasant I think the main value proposition is getting a consistent identity/versioning and trust story. I am not too worried about metadata stuff like tags/logoUrl. It is going to be painful if we can't align those security/identity issues between A2A and MCP.
There was a problem hiding this comment.
@darrelmiller in the first meeting (which I know you were not on), MCP's perspective (via David and Caitie) was that MCP is keen to keep things simple at this time. Identity (beyond web-based DNS) and trust will likely be important at some point, but MCP isn't ready to lock in assumptions about how it should work.
Where there is alignment is in first collaborating on the discovery story. If the group feels that the concerns are inherently coupled and we cannot proceed with a shared discovery approach without aligning on identity/trust, then I think we need to take a step back and revisit the scope first before workshopping the details.
There was a problem hiding this comment.
@tadasant I agree with your approach for discovery. We do not want to force an extra hop, nor do we want to force MCP into an envelope that contains governance/trust fields you aren't ready for today. The ai-catalog should simply be a discovery list that can point directly to native MCP Server Cards. Please see my comments below for more details about that.
…update naming from PR Agent-Card#18 Co-authored-by: Luca Muscariello <lumuscar@cisco.com>
darrelmiller
left a comment
There was a problem hiding this comment.
I am approving this, not because I think everything is right, but I think we need a baseline in the main branch that we can debate and iterate over. Working in all these different PRs is making us go in circles.
muscariello
left a comment
There was a problem hiding this comment.
Approving to make progress based on all the comments.
| "finance", | ||
| "trading" | ||
| ], | ||
| "cardUrl": "https://api.acme-corp.com/cards/acme-finance-agent.json", |
There was a problem hiding this comment.
how do I know if this is an MCP Server Card or an A2A Card or something else?
There was a problem hiding this comment.
@ToddSegal We have two clean options. We could implicitly hint via the card's filename (e.g., agent.json-> A2A, mcp.json -> MCP, ai-card.json -> Unified card). However, the more robust approach is for the catalog entries to simply use an explicit type discriminator alongside the URL. For example:
{ "type": "mcp-server", "url": "https://.../mcp-card.json" }
{ "type": "a2a-agent", "url": "https://.../agent-card.json" }
This gives us a unified discovery layer immediately, while MCP can keep its native card and allowing A2A to use the heavier ai-card envelope (which requires identity, tags, and trust metadata for autonomous routing) (which also will become the unified card when mcp is ready to migrate)
Initial Draft of AI Card & AI Catalog Specifications
Note: This PR has been updated to reflect the converged schema architecture co-authored and designed in collaboration with @muscariello .
Key Architecture Decisions:
protocolsmap (e.g.,protocols.a2a,protocols.mcp).artifactsarray.Summary
This PR introduces the foundational draft for the AI Card and AI Catalog specifications, creating a unified framework for describing and discovering AI services.
Key Changes
Unified AI Card Schema (
ai-card-cddl.md):id,name,description, andpublisherat the top level.interfacesmap, keyed by protocol type (e.g.,"a2a","mcp"). This allows a single card to describe multiple interaction protocols, with protocol-specific details encapsulated in aprotocolSpecificblock.trustsection is optional, including fields forprivacyPolicyUrlandtermsOfServiceUrl.Attestationfield using a reference pattern (uri,mediaType,digest) for both publisher identity proofs and compliance evidence, supporting remote and inline credentials.maturityto indicate lifecycle stages ("preview","stable","deprecated").signaturefield for card integrity (detached JWS).identityTypehints foridfields (e.g.,"did","spiffe").AI Catalog for Discovery (
ai-catalog-cddl.md):/.well-known/ai-catalog.json).HostInfofor catalog metadata andAIServiceEntryobjects for lightweight service discovery, linking to full AI Cards viacardUrl.Examples and Documentation:
ai-card-example.mdandai-catalog-example.mdprovide complete JSON examples, showcasing dual-protocol agents and catalog files.comparison.mdtable maps fields from previous A2A and MCP card proposals to the unified structure, emphasizing the "lift common fields, delegate protocol specifics" design.Summary
This PR proposes a comprehensive, extensible, and trust-oriented foundation for an interoperable AI service ecosystem. It unifies metadata standards, simplifies multi-protocol support, and introduces a discovery mechanism to streamline integration workflows.
This table below shows how the fields from A2A and MCP map to the unified AI Card structure, based on A2A/MCP:
AgentCard(Spec)Server Card(Proposal)AI Card(V1)serverInfo.nameid(Root URI) +identityTypenameserverInfo.titlenamedescriptiondescriptiondescriptionicon_urliconUrllogoUrl(Rec: Data URI)provider(Object)serverInfopublisher(Object withid,name)signatures(Optional)trust(Optional Object: Proofs, Policies)protocols(Map:"a2a": {...},"mcp": {...})urltransport.endpointprotocols[x].protocolSpecific(Delegated)securitySchemesauthenticationprotocols[x].protocolSpecific(Delegated)skillstools,resourcesprotocols[x].protocolSpecific(Delegated)versionserverInfo.versionspecVersion(Card Ver) +updatedAtAI-catalog example:
{ "$schema": "https://agent-card.github.io/spec/sep-0015/catalog-schema.json", "specVersion": "1.0", "host": { "name": "Acme Services Inc.", "id": "did:example:org-acme-corp", "documentationUrl": "https://docs.acme-corp.com/agents" }, "records": [ { "id": "did:example:agent-finance-001", "name": "Acme Finance Agent", "description": "Multi-protocol finance agent.", "tags": [ "finance", "trading" ], "cardUrl": "https://api.acme-corp.com/cards/acme-finance-agent.json", "updatedAt": "2026-02-22T16:30:00Z" }, { "id": "urn:example:data:market-dataset-2026q1", "name": "Market Dataset Q1 2026", "description": "Artifact-focused card for training and evaluation.", "tags": [ "dataset", "finance" ], "cardUrl": "https://api.acme-corp.com/cards/market-dataset-2026q1.json", "updatedAt": "2026-02-22T16:00:00Z" } ] }AI-card example
{ "$schema": "https://agent-card.github.io/spec/sep-0015/schema.json", "specVersion": "1.0", "cardVersion": "2026.02.22", "identifier": "urn:example:agent-finance-001", "displayName": "Acme Finance Agent", "description": "Executes finance workflows through multiple protocol adapters.", "publisher": { "id": "did:example:org-acme", "name": "Acme Financial Corp", "identityType": "did" }, "protocols": { "a2a": { "id": "protocol/a2a", "version": "0.1.0", "required": true, "data": { "protocolVersion": "0.3.0", "locators": [ { "type": "https", "role": "api", "uri": "https://api.acme-finance.com/a2a/v1" } ], "skills": [ { "id": "skill-stock-analysis", "name": "Run Stock Analysis" } ] } }, "mcp": { "id": "protocol/mcp", "version": "0.1.0", "required": true, "data": { "protocolVersion": "2025-06-18", "locators": [ { "type": "https", "role": "api", "uri": "https://api.acme-finance.com/mcp/v1" } ], "capabilities": { "tools": { "listChanged": true } } } } }, "trust": { "id": "did:example:agent-finance-001", "identityType": "did", "trustSchema": { "id": "https://trust.acme-finance.com/schemas/ai-card-trust-profile", "version": "1.0", "governanceUri": "https://trust.acme-finance.com/policies/ai-card-trust", "verificationMethods": [ "did", "x509", "dns-01" ] }, "privacyPolicyUrl": "https://acme-finance.com/legal/privacy", "termsOfServiceUrl": "https://acme-finance.com/legal/terms", "provenance": [ { "relation": "materializedFrom", "sourceId": "urn:example:data:market-dataset-2026q1", "sourceDigest": "sha256:9999888877776666555544443333222211110000aaaabbbbccccddddeeeeffff", "registryUri": "oci://registry.example.com/ai-data/market-dataset@sha256:9999888877776666555544443333222211110000aaaabbbbccccddddeeeeffff", "statementUri": "https://trust.acme-finance.com/provenance/finance-agent-runtime-20260222.dsse.json", "signatureRef": "did:example:org-acme#keys-1" } ], "attestations": [ { "type": "SOC2-Type2", "uri": "https://trust.acme-finance.com/reports/soc2-latest.pdf", "mediaType": "application/pdf", "digest": "sha256:a1b2c3d4" } ] }, "signatures": [ { "format": "jws-compact", "keyId": "did:example:org-acme#keys-1", "createdAt": "2026-02-22T16:30:00Z", "value": "eyJhbGciOiJFUzI1NiJ9..detached-signature" } ], "createdAt": "2026-02-22T16:00:00Z", "updatedAt": "2026-02-22T16:30:00Z" }