Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ yarn.lock @backsta
/workspaces/linguist @backstage/community-plugins-maintainers @awanlin
/workspaces/linkerd @backstage/community-plugins-maintainers
/workspaces/manage @backstage/community-plugins-maintainers @grantila
/workspaces/mcp-capabilities @backstage/community-plugins-maintainers @jh-sh @0rc
/workspaces/mcp-chat @backstage/community-plugins-maintainers @Lucifergene @christoph-jerolimov @Eswaraiahsapram
/workspaces/mend @backstage/community-plugins-maintainers @NormanWenzelWSS @rupalvihol @hetsaliya-crestdata
/workspaces/microsoft-calendar @backstage/community-plugins-maintainers
Expand Down
8 changes: 8 additions & 0 deletions workspaces/mcp-capabilities/.changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
11 changes: 11 additions & 0 deletions workspaces/mcp-capabilities/.changeset/add-mcp-capabilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@backstage-community/plugin-mcp-capabilities': minor
'@backstage-community/plugin-mcp-capabilities-backend': minor
'@backstage-community/plugin-mcp-capabilities-common': minor
---

Introduce the MCP Capabilities plugins for native `API` / `spec.type: mcp-server` catalog entities.

- **Backend**: connects to each MCP server (streamable-http) to discover its tools, resources, and prompts. A catalog processor enriches the entity with a summary (capabilities, counts, and tool names for search), and an on-demand endpoint serves the full live detail.
- **Frontend** (new frontend system, Backstage UI): an overview card with the server's identity and capabilities, and a "Capabilities" tab listing tools, resources, and prompts.
- **Common**: shared types and a catalog model layer that additively extends the native `mcp-server` schema (existing entities remain valid).
14 changes: 14 additions & 0 deletions workspaces/mcp-capabilities/.changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"privatePackages": {
"tag": false,
"version": false
}
}
8 changes: 8 additions & 0 deletions workspaces/mcp-capabilities/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.git
.yarn/cache
.yarn/install-state.gz
node_modules
packages/*/src
packages/*/node_modules
plugins
*.local.yaml
1 change: 1 addition & 0 deletions workspaces/mcp-capabilities/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
playwright.config.ts
1 change: 1 addition & 0 deletions workspaces/mcp-capabilities/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../../.eslintrc.cjs');
54 changes: 54 additions & 0 deletions workspaces/mcp-capabilities/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# macOS
.DS_Store

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Coverage directory generated when running tests with coverage
coverage

# Dependencies
node_modules/

# Yarn 3 files
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Node version directives
.nvmrc

# dotenv environment variables file
.env
.env.test

# Build output
dist
dist-types

# Temporary change files created by Vim
*.swp

# MkDocs build output
site

# Local configuration files
*.local.yaml

# Sensitive credentials
*-credentials.yaml

# vscode database functionality support files
*.session.sql

# E2E test reports
e2e-test-report/
5 changes: 5 additions & 0 deletions workspaces/mcp-capabilities/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
dist-types
coverage
.vscode
.eslintrc.js
4 changes: 4 additions & 0 deletions workspaces/mcp-capabilities/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
approvedGitRepositories:
- '**'

enableScripts: true
45 changes: 45 additions & 0 deletions workspaces/mcp-capabilities/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# MCP Capabilities for Backstage

Plugins that enrich native MCP server catalog entities (`kind: API`,
`spec.type: mcp-server`) with their live **capabilities** — the tools,
resources, and prompts each server exposes.

## Plugins

- [mcp-capabilities](./plugins/mcp-capabilities/README.md) — frontend (new
frontend system, [Backstage UI](https://backstage.io/docs/getting-started/ui)):
an overview card and a **Capabilities** tab on the entity page.
- [mcp-capabilities-backend](./plugins/mcp-capabilities-backend/README.md) —
backend: connects to each MCP server, enriches its catalog entity, and serves
live tool/resource/prompt detail.
- [mcp-capabilities-common](./plugins/mcp-capabilities-common/README.md) — shared
types and the schema-extension catalog model layer.

## How it works

Each `mcp-server` API entity declares its endpoint in `spec.remotes`. The backend
connects over the MCP streamable-http transport to discover what the server
exposes:

- a catalog **processor** writes a summary (capabilities, counts, and tool names
for search) onto the entity — powering the overview card and catalog search;
- an on-demand endpoint, `GET /api/mcp-capabilities/spec?entityRef=…`, returns the
full live tool/resource/prompt detail — powering the Capabilities tab.

The common package's catalog model layer **extends** the native `mcp-server`
schema additively (via `updateKind`), so entities that haven't been enriched yet
remain valid.

> **Frontend system:** these plugins target the **new** Backstage frontend
> system. Legacy-frontend-system support is a planned follow-up.

## Local development

```sh
yarn install
yarn start
```

## Credits

Made at [EPAM](https://www.epam.com), with love for the community. ❤️
1 change: 1 addition & 0 deletions workspaces/mcp-capabilities/backstage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "version": "1.52.0" }
4 changes: 4 additions & 0 deletions workspaces/mcp-capabilities/bcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"autoVersionBump": false,
"knipReports": false
}
62 changes: 62 additions & 0 deletions workspaces/mcp-capabilities/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "@internal/mcp-capabilities",
"version": "1.0.0",
"private": true,
"engines": {
"node": "22 || 24"
},
"scripts": {
"start": "backstage-cli repo start",
"tsc": "tsc",
"tsc:full": "tsc --skipLibCheck false --incremental false",
"build:all": "backstage-cli repo build --all",
"build:api-reports": "yarn build:api-reports:only --tsc",
"build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented --validate-release-tags",
"build:knip-reports": "backstage-repo-tools knip-reports",
"clean": "backstage-cli repo clean",
"test": "backstage-cli repo test",
"test:all": "backstage-cli repo test --coverage",
"fix": "backstage-cli repo fix",
"lint": "backstage-cli repo lint --since origin/main",
"lint:all": "backstage-cli repo lint",
"prettier:check": "prettier --check .",
"prettier:fix": "prettier --write .",
"new": "backstage-cli new --scope @backstage-community",
"postinstall": "cd ../../ && yarn install"
},
"workspaces": [
"packages/*",
"plugins/*"
],
"repository": {
"type": "git",
"url": "https://github.com/backstage/community-plugins",
"directory": "workspaces/mcp-capabilities"
},
"devDependencies": {
"@backstage/cli": "^0.36.3",
"@backstage/cli-defaults": "^0.1.3",
"@backstage/e2e-test-utils": "^0.1.2",
"@backstage/repo-tools": "^0.17.3",
"@changesets/cli": "^2.27.1",
"knip": "^5.27.4",
"node-gyp": "^10.0.0",
"prettier": "^2.3.2",
"typescript": "~5.8.0"
},
"resolutions": {
"@types/react": "^18",
"@types/react-dom": "^18",
"tarn": "3.0.2"
},
"prettier": "@backstage/cli/config/prettier",
"lint-staged": {
"*.{js,jsx,ts,tsx,mjs,cjs}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md}": [
"prettier --write"
]
}
}
9 changes: 9 additions & 0 deletions workspaces/mcp-capabilities/plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# The Plugins Folder

This is where your own plugins and their associated modules live, each in a
separate folder of its own.

If you want to create a new plugin here, go to your project root directory, run
the command `yarn new`, and follow the on-screen instructions.

You can also check out existing plugins on [the plugin marketplace](https://backstage.io/plugins)!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# @backstage-community/plugin-mcp-capabilities-backend

Backend for the MCP Capabilities suite. It connects to the MCP servers described
by native `API` / `spec.type: mcp-server` catalog entities (reading their
`spec.remotes[].url`) and exposes what they offer.

Two parts, both reading `spec.remotes` off the catalog entity (no duplicate
config):

1. **Catalog module** (`catalogModuleMcpCapabilities`) — a processor that writes a
discovered summary (capabilities, counts, `serverInfo`, and a flat list of tool
names for catalog search) onto each `mcp-server` entity. Failures are skipped
gracefully, so an unreachable server never fails catalog ingestion.
2. **Backend plugin** — an on-demand router,
`GET /api/mcp-capabilities/spec?entityRef=<ref>`, returning the full live
tool / resource / prompt detail for the Capabilities tab.

The MCP client speaks the streamable-http transport with the JSON-RPC handshake
(`initialize` → `notifications/initialized` → capability-gated
`tools/list` / `resources/list` / `prompts/list`), is SSE-aware, and handles the
`Mcp-Session-Id` header.

## Installation

```sh
yarn --cwd packages/backend add @backstage-community/plugin-mcp-capabilities-backend
```

```ts
// packages/backend/src/index.ts
import { provideStaticCatalogModel } from '@backstage/plugin-catalog-node/alpha';
import { mcpServerApiEntityModel } from '@backstage/catalog-model/alpha';
import { mcpServerEnrichmentModelLayer } from '@backstage-community/plugin-mcp-capabilities-common';
import { catalogModuleMcpCapabilities } from '@backstage-community/plugin-mcp-capabilities-backend';

const backend = createBackend();

// Native mcp-server kind + the additive enrichment model layer
backend.add(
provideStaticCatalogModel({
layers: [mcpServerApiEntityModel, mcpServerEnrichmentModelLayer],
}),
);

// Discovery: enrichment processor + on-demand /spec router
backend.add(import('@backstage-community/plugin-mcp-capabilities-backend'));
backend.add(catalogModuleMcpCapabilities);

backend.start();
```

Register some native `mcp-server` entities, e.g.:

```yaml
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: aws-docs
spec:
type: mcp-server
lifecycle: production
owner: group:default/guests
remotes:
- type: streamable-http
url: https://your-mcp-server.example.com/mcp
```

Verify:

```sh
curl 'http://localhost:7007/api/mcp-capabilities/spec?entityRef=api:default/aws-docs'
```

## Limitations

- **Network reachability (backend egress).** Discovery runs from the Backstage
**backend** — the catalog processor and the `/spec` route — which connect
_outbound_ to each server's `spec.remotes[].url` over the MCP streamable-http
transport. Your backend must therefore be able to reach every MCP server you
register. Servers on a private network, behind a VPN, or firewalled need the
backend to have a route to them (VPC/peering, allow-listed egress, or an HTTP
proxy). The browser never connects to the MCP server directly, so this is a
backend-egress concern, not a CORS one.
- **Unreachable or slow servers.** Discovery is time-boxed (15s in the catalog
processor, 30s for the on-demand `/spec` route). A server that is unreachable or
times out is skipped gracefully: the processor leaves the entity unchanged, and
`/spec` returns an error that the Capabilities tab surfaces.
- **Per-request auth.** Remotes requiring signed requests (e.g. AWS Bedrock
AgentCore Gateway, SigV4) are not yet signed — those remotes are skipped by the
processor and error from `/spec`. Per-remote auth is a possible enhancement (depends on how future backstage shift to `connections` plays out).

## Development

`yarn start` in this directory runs the plugin standalone (see [`/dev`](./dev)).

## Exports

- default — the backend plugin (mounts the `/spec` router)
- `catalogModuleMcpCapabilities` — the enrichment catalog module

## Credits

Made at [EPAM](https://www.epam.com), with love for the community. ❤️
Loading
Loading