Skip to content

registry OpenAPI: define community-mirror lifecycle endpoints (/api/registry/mirrors) + schemas so SDKs can generate types #5384

@bokelley

Description

@bokelley

Summary

The registry service implements a community-mirror lifecycle (publish / get / list persisted adagents mirrors keyed by platform), but those endpoints and their schemas are not defined in the registry OpenAPI spec (static/openapi/registry.yaml, served at https://agenticadvertising.org/openapi/registry.yaml). As a result, every SDK has to hand-roll the DTOs instead of generating typed models from the spec.

Evidence

  • The spec (live, ~8967 lines) has no /api/registry/mirrors path and no CommunityMirror* schema — the only "mirror" hits are incidental prose. The concept is mentioned in the POST /api/adagents/create description ("…authorized_agents may be empty for a catalog-only community mirror…") but the persisted lifecycle is undocumented.
  • JS SDK added a client for these endpoints with hand-written TS DTOs (not generated): adcontextprotocol/adcp-client#2183 (lifecycle client) and #2187 (upsert helper) — CommunityMirrorAdagentsCatalog, PublishCommunityMirrorAdagentsResponse, ListCommunityMirrorAdagentsResponse, CommunityMirrorAdagentsConfig.
  • Python SDK hit the same wall: adcontextprotocol/adcp-client-python#925 / PR #929 currently type these as dict[str, Any] because there is no generated model in adcp.types.registry to use.

Because both SDKs generate registry types from this OpenAPI spec, the missing definitions force divergent, reverse-engineered DTOs per language — exactly what the spec-as-source-of-truth model is meant to prevent.

Endpoints to define (shapes from the JS implementation — please confirm against the service)

  • PUT /api/registry/mirrors/{platform} — publish a community-mirror adagents catalog. Auth required. Body is the built catalog (authorized_agents: [], catalog_etag, formats, optional properties, superseded_by). platform normalized to ^[a-z0-9_-]{1,64}$; each properties[].platform must normalize to the route platform.
  • GET /api/registry/mirrors/{platform} — fetch one; 404 when absent. Response wrapper: { platform, superseded_by, adagents_json }.
  • GET /api/registry/mirrors — list with optional limit / offset; response { mirrors: [...], total }.

Schemas to define

CommunityMirrorAdagentsCatalog, the publish response, the get-wrapper, the list response, and the publish/upsert input config.

Secondary (optional, same family)

POST /api/adagents/create is also untyped in the Python client (dict[str, Any]) — its request/response are likewise not modeled. Worth defining its response schema while this area is being touched, so the whole adagents/mirror family is generated rather than hand-rolled.

Why this matters

Spec is the source of truth; the SDKs run datamodel-code-generator against it. Undefined endpoints → hand-written DTOs that drift from the service and from each other across JS/Python/Go. Adding these to static/openapi/registry.yaml lets every SDK generate real types and delete the stopgap dicts.

Cross-references

  • JS: adcontextprotocol/adcp-client#2183, #2187
  • Python: adcontextprotocol/adcp-client-python#925, #929

(Surfaced while wiring registry community-mirror parity into the Python SDK. The exact request/response shapes above are reverse-engineered from the JS client and should be validated against the registry service implementation before being committed to the spec.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.enhancementNew feature or requestschemaJSON Schema source-of-truth: definitions, codegen artifacts, validation, hygiene

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions