redhat-developer / redhat-developer/rhdh-plugins
feat(ai-integrations): implement MCP registry provider backend plugin - 1 / 1 (`mcp-registry-provider`)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 48
- Forks
- 120
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 337
Description
ref: https://redhat.atlassian.net/browse/RHIDP-15655
Summary
Implement a Backstage catalog entity provider backend plugin that periodically ingests MCP servers from one configured MCP Registry: list servers via cursor pagination, transform each server.json through the composed mcp-registry-server-mapping transform (#4813 + #4795), stamp sync status and provider attribution, and commit a full mutation so the catalog converges to the registry’s current server set.
This capability is specified in OpenSpec change mcp-registry-provider and is the first runtime consumer of the sibling mapping library.
Normative spec (source of truth):
openspec/changes/mcp-registry-provider/specs/mcp-registry-provider/spec.md
Related design decisions: D1 (config shape), D2 (catalog-backend-module), D3 (schedule defaults), D4 (pagination), D5–D8 (mutation, last-good retention, sync status) in
openspec/changes/mcp-registry-provider/design.md
Problem
The mapping change defines a pure server.json → mcp-server API transform but leaves ingestion out of scope. Operators who point RHDH at a registry still get no catalog entities until a scheduled provider fetches registry pages, applies the transform, and prunes removed servers.
Scope
In scope
catalog-backend-moduleplugin:createBackendModule,EntityProviderwithgetProviderName()/ mutationlocationKeymcp-registry-provider.- Config at
catalog.providers.mcpRegistry(single object):baseUrl(required), optionalbaseName,apiVersion(defaultv1),schedule,pageLimit(default10pages/sync),pageSize(?limit=),defaultOwner; inert when key absent; reject keyed multi-registry maps. - Scheduler-driven sync only (no sync from
connect()); default schedule 30m / 3m timeout. - Registry client:
GET <baseUrl>/<apiVersion>/servers, opaque cursor pagination, page safeguards (page cap, repeated cursor). - Per-entry mapping via sibling transform (
defaultOwner, optionalbaseName→ prefix); no reimplementation of mapping rules. - Full mutation on successful runs; no mutation on failed runs (transport/protocol/pagination trip).
- Resilient per-entry failures: log, continue; last-good retention (D6) with
redhat.com/rhdh-mcp-registry-sync-statusok/degraded. backstage.io/managed-by-location:url:+ normalizedbaseUrl.
Out of scope
- The
server.json→ entity transform itself (#4813, #4795). - Registry proxy/pass-through API, auth credentials, multiple registries, runtime MCP invocation, catalog UI.
Implementation checklist (from tasks.md)
Group 1 — scaffolding:
- 1.1
catalog-backend-modulepackage layout. - 1.2 Backend module skeleton + extension point.
- 1.3 README install / app-config example.
Group 2 — configuration:
- 2.1
config.d.tswith@visibility backend. - 2.2 Absent config → no provider registered.
- 2.3 Validation, defaults (
apiVersion, schedule,pageLimit). - 2.4 Config unit tests.
Group 3 — registry client:
- 3.1–3.6 Types, URL construction, cursor loop, safeguards, errors, client tests.
Group 4 — provider & scheduling:
- 4.1–4.5
EntityProvider, scheduler wiring, full mutation, annotations, tests.
Group 5 — mapping integration:
- 5.1–5.3 Invoke mapping library; per-entry isolation; integration tests.
Group 6 — verification & docs:
- 6.1–6.5 E2E test, schema check,
apiVersiondocs, README, CI.
Acceptance criteria (map to spec scenarios)
| Area | Must hold |
|---|---|
| Config | Single object; missing baseUrl / multi-registry map fail fast; defaults for schedule, apiVersion, pageLimit. |
| Schedule | Scheduler-only; documented default; optional initialDelay. |
| Pagination | Full cursor traversal; optional pageSize; pageLimit caps pages; repeated cursor fails run. |
| Endpoint | <baseUrl>/<apiVersion>/servers with slash normalization. |
| Mapping | Delegates to #4813/#4795; defaultOwner / baseName passed as caller overrides. |
| Mutation | Full sync prunes removed servers; failed run leaves prior catalog state. |
| Resilience | One bad entry does not abort batch; last-good + degraded when applicable. |
| Attribution | locationKey, managed-by-location, sync status per spec. |
Dependencies
- Prerequisite: Composed
mcp-registry-server-mappinglibrary — #4813 (direct mapping) and #4795 (annotation projection). - Upstream: Backstage
EntityProvider,SchedulerService, MCP Registry generic API.
References
- OpenSpec change:
openspec/changes/mcp-registry-provider/ - Mapping change:
openspec/changes/mcp-registry-server-mapping/ - GitHub issues: #4813, #4795
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with openspec/changes/mcp-registry-provider/specs/mcp-registry-provider/spec.md, design.md, and tasks.md, then inspect the sibling mcp-registry-server-mapping work and Backstage EntityProvider and SchedulerService entry points. Done means the provider package, configuration, paginated client, scheduled synchronization, mapping integration, tests, schema checks, documentation, and CI verification satisfy the listed acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100