Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ 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
Comment thread
jh-sh marked this conversation as resolved.
Outdated
/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
}
61 changes: 61 additions & 0 deletions workspaces/mcp-capabilities/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"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"
},
"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