refactor(catalog-model): move mcp-server model to opt-in backend module

Moves the mcp-server specType registration out of the default catalog
entity model into a separate backend module following the same pattern
as the AiResource module. Types and validators are now alpha exports.

Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
benjdlambert
2026-05-18 19:06:34 +02:00
parent 2a640474c2
commit 2003dcb4db
14 changed files with 201 additions and 42 deletions
@@ -491,6 +491,11 @@ export const isAiResourceEntity: (
entity: Entity,
) => entity is AiResourceEntityV1alpha1;
// @alpha
export function isMcpServerApiEntity(
entity: Entity,
): entity is McpServerApiEntity;
// @alpha
export const isSkillAiResourceEntity: (
entity: Entity,
@@ -501,6 +506,34 @@ export type KindValidator = {
check(entity: Entity): Promise<boolean>;
};
// @alpha
export interface McpServerApiEntity extends Entity {
// (undocumented)
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
// (undocumented)
kind: 'API';
// (undocumented)
spec: {
type: 'mcp-server';
lifecycle: string;
owner: string;
system?: string;
remotes: McpServerRemote[];
};
}
// @alpha
export const mcpServerApiEntityModel: CatalogModelLayer;
// @alpha
export const mcpServerApiEntityValidator: KindValidator;
// @alpha
export type McpServerRemote = {
type: string;
url: string;
};
// @alpha
export interface SkillAiResourceEntityV1alpha1 extends Entity {
// (undocumented)
-30
View File
@@ -273,11 +273,6 @@ export function isLocationEntity(
entity: Entity,
): entity is LocationEntityV1alpha1;
// @public
export function isMcpServerApiEntity(
entity: Entity,
): entity is McpServerApiEntity;
// @public (undocumented)
export function isResourceEntity(
entity: Entity,
@@ -337,31 +332,6 @@ export const locationEntityV1alpha1Validator: KindValidator;
// @public
export function makeValidator(overrides?: Partial<Validators>): Validators;
// @public
export interface McpServerApiEntity extends Entity {
// (undocumented)
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
// (undocumented)
kind: 'API';
// (undocumented)
spec: {
type: 'mcp-server';
lifecycle: string;
owner: string;
system?: string;
remotes: McpServerRemote[];
};
}
// @public
export const mcpServerApiEntityValidator: KindValidator;
// @public
export type McpServerRemote = {
type: string;
url: string;
};
// @public
export class NoForeignRootFieldsEntityPolicy implements EntityPolicy {
constructor(knownFields?: string[]);
@@ -23,7 +23,7 @@ import { ajvCompiledJsonSchemaValidator } from './util';
* An MCP (Model Context Protocol) server represented as an API entity
* (spec.type: 'mcp-server').
*
* @public
* @alpha
*/
export interface McpServerApiEntity extends Entity {
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
@@ -40,7 +40,7 @@ export interface McpServerApiEntity extends Entity {
/**
* A transport endpoint for an MCP server.
*
* @public
* @alpha
*/
export type McpServerRemote = {
type: string;
@@ -50,7 +50,7 @@ export type McpServerRemote = {
/**
* {@link KindValidator} for the `mcp-server` specType of API entities.
*
* @public
* @alpha
*/
export const mcpServerApiEntityValidator =
ajvCompiledJsonSchemaValidator(mcpServerSchema);
@@ -58,7 +58,7 @@ export const mcpServerApiEntityValidator =
/**
* Type guard: narrows an entity to the MCP server API subtype.
*
* @public
* @alpha
*/
export function isMcpServerApiEntity(
entity: Entity,
@@ -16,9 +16,13 @@
import { compileCatalogModel } from '../model/compileCatalogModel';
import { defaultCatalogEntityModel } from '../model/defaultCatalogEntityModel';
import { mcpServerApiEntityModel } from './McpServerApiEntity';
describe('apiEntityModel mcp-server dispatch', () => {
const model = compileCatalogModel([defaultCatalogEntityModel]);
const model = compileCatalogModel([
defaultCatalogEntityModel,
mcpServerApiEntityModel,
]);
it('routes mcp-server and non-mcp-server v1alpha1 entities to different schemas', () => {
const mcp = model.getKind({
@@ -19,11 +19,6 @@ export type {
ApiEntityV1alpha1 as ApiEntity,
ApiEntityV1alpha1,
} from './ApiEntityV1alpha1';
export {
isMcpServerApiEntity,
mcpServerApiEntityValidator,
} from './McpServerApiEntity';
export type { McpServerApiEntity, McpServerRemote } from './McpServerApiEntity';
export { componentEntityV1alpha1Validator } from './ComponentEntityV1alpha1';
export type {
ComponentEntityV1alpha1 as ComponentEntity,
@@ -15,7 +15,6 @@
*/
import { apiEntityModel } from '../kinds/ApiEntityV1alpha1';
import { mcpServerApiEntityModel } from '../kinds/McpServerApiEntity';
import { componentEntityModel } from '../kinds/ComponentEntityV1alpha1';
import { domainEntityModel } from '../kinds/DomainEntityV1alpha1';
import { groupEntityModel } from '../kinds/GroupEntityV1alpha1';
@@ -37,7 +36,6 @@ export const defaultCatalogEntityModel = createCatalogModelLayer({
layerId: 'catalog.backstage.io/default-entity-model',
builder: model => {
model.import(apiEntityModel);
model.import(mcpServerApiEntityModel);
model.import(componentEntityModel);
model.import(domainEntityModel);
model.import(groupEntityModel);