create-app - Added the mcp-actions-backend plugin
Signed-off-by: Andre Wanlin <awanlin@spotify.com> Changes based on feedback Signed-off-by: Andre Wanlin <awanlin@spotify.com> Minor corrections Signed-off-by: Andre Wanlin <awanlin@spotify.com> Default to false Signed-off-by: Andre Wanlin <awanlin@spotify.com> Corrections Signed-off-by: Andre Wanlin <awanlin@spotify.com> Feedback Signed-off-by: Andre Wanlin <awanlin@spotify.com> Feedback changes Signed-off-by: Andre Wanlin <awanlin@spotify.com> Feedback changes Signed-off-by: Andre Wanlin <awanlin@spotify.com> Added tip Signed-off-by: Andre Wanlin <awanlin@spotify.com> More feedback changes Signed-off-by: Andre Wanlin <awanlin@spotify.com> Fixed typos Signed-off-by: Andre Wanlin <awanlin@spotify.com> Reorder auth Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Added the `mcp-actions-backend` and `plugin-auth` plugins
|
||||
+56
-18
@@ -44,10 +44,14 @@ You can configure the name and description of your Backstage MCP server with the
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
mcpActions:
|
||||
name: 'My MCP Server' # defaults to "backstage"
|
||||
description: 'Tools for interacting with My MCP Server' # optional
|
||||
name: 'My Company Backstage' # defaults to "backstage"
|
||||
description: 'Tools for managing your software catalog, creating new services from templates, and exploring your developer portal' # optional
|
||||
```
|
||||
|
||||
:::tip
|
||||
Keep the following in mind when picking the name and description. The description should answer "what can I do with these tools?" from the perspective of an AI agent deciding whether to use this server — not "what is this server?". That means describing Backstage capabilities (catalog, scaffolder, etc.), not the MCP protocol or server identity.
|
||||
:::
|
||||
|
||||
## Namespaced Tool Names
|
||||
|
||||
By default, MCP tool names include the plugin ID prefix to avoid collisions across plugins. For example, an action registered as `greet-user` by `my-custom-plugin` is exposed as `my-custom-plugin.greet-user`.
|
||||
@@ -146,20 +150,20 @@ Authorization: Bearer <token>
|
||||
For more details about external access tokens and service-to-service authentication, see the
|
||||
[Service-to-Service Auth documentation](../auth/service-to-service-auth.md).
|
||||
|
||||
### Experimental: Dynamic Client Registration
|
||||
### Experimental Authentication methods
|
||||
|
||||
:::warning
|
||||
This feature is highly experimental and only works with the New Frontend System. Proceed with caution.
|
||||
:::
|
||||
The MCP Actions Backend supports two experimental authentication methods based on the MCP specification:
|
||||
|
||||
You can configure the auth-backend and install the auth frontend plugin to enable **Dynamic Client Registration** with MCP clients. This means you do not need to manually configure a token in your MCP client settings. Instead, a client can request a token on your behalf. When adding the MCP server to an MCP client like Cursor or Claude, a popup requiring your approval will open in your Backstage instance (powered by the auth plugin).
|
||||
- [Client ID Metadata Documents (CIMD)](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents)
|
||||
- [Dynamic Client Registration (DCR)](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#dynamic-client-registration)
|
||||
|
||||
**Requirements:**
|
||||
They have the following requirements:
|
||||
|
||||
- You must be using the [New Frontend System](../frontend-system/architecture/00-index.md).
|
||||
- The `@backstage/plugin-auth-backend` plugin must be configured.
|
||||
- The new `@backstage/plugin-auth` frontend plugin must be configured.
|
||||
|
||||
**Installation:**
|
||||
Follow these steps to install and configure the new `@backstage/plugin-auth` frontend plugin:
|
||||
|
||||
1. Install the `@backstage/plugin-auth` frontend plugin:
|
||||
|
||||
@@ -180,17 +184,51 @@ You can configure the auth-backend and install the auth frontend plugin to enabl
|
||||
});
|
||||
```
|
||||
|
||||
3. Enable the feature:
|
||||
#### Client ID Metadata Documents
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
auth:
|
||||
experimentalDynamicClientRegistration:
|
||||
enabled: true
|
||||
:::warning
|
||||
This feature is highly experimental; proceed with caution. Client support is also currently limited but quickly being implemented.
|
||||
:::
|
||||
|
||||
# Optional: limit valid callback URLs for added security
|
||||
allowedRedirectUriPatterns:
|
||||
- cursor://*
|
||||
```
|
||||
The [November 2025 MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) outlined a new authorization method to replace Dynamic Client Registration called [Client ID Metadata Documents (CIMD)](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents).
|
||||
|
||||
Using Client ID Metadata Documents means you do not need to manually configure a token in your MCP client settings. Instead, a client can request a token on your behalf. When adding the MCP server to an MCP client like Cursor or Claude, a popup requiring your approval will open in your Backstage instance (powered by the `auth` plugin).
|
||||
|
||||
This can be enabled in the `auth-backend` plugin by using the `auth.experimentalClientIdMetadataDocuments.enabled` flag in config:
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
auth:
|
||||
experimentalClientIdMetadataDocuments:
|
||||
enabled: true
|
||||
# Optional: restrict which `client_id` URLs are allowed (defaults to ['*'])
|
||||
allowedClientIdPatterns:
|
||||
- 'https://example.com/*'
|
||||
- 'https://*.trusted-domain.com/*'
|
||||
# Optional: restrict which redirect URIs are allowed (defaults to ['*'])
|
||||
allowedRedirectUriPatterns:
|
||||
- 'http://localhost:*'
|
||||
- 'https://*.example.com/*'
|
||||
```
|
||||
|
||||
#### Dynamic Client Registration
|
||||
|
||||
:::warning
|
||||
This feature is highly experimental; proceed with caution. This method will likely be deprecated and replaced by [Client ID Metadata Documents](#client-id-metadata-documents) in the future. Only use in cases where clients do not yet support Client ID Metadata Documents.
|
||||
:::
|
||||
|
||||
Using Dynamic Client Registration means you do not need to manually configure a token in your MCP client settings. Instead, a client can request a token on your behalf. When adding the MCP server to an MCP client like Cursor or Claude, a popup requiring your approval will open in your Backstage instance (powered by the `auth` plugin).
|
||||
|
||||
This can be enabled in the `auth-backend` plugin by using the `auth.experimentalDynamicClientRegistration.enabled` flag in config:
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
auth:
|
||||
experimentalDynamicClientRegistration:
|
||||
enabled: true
|
||||
|
||||
# Optional: limit valid callback URLs for added security
|
||||
allowedRedirectUriPatterns:
|
||||
- cursor://*
|
||||
```
|
||||
|
||||
## Configuring MCP Clients
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ jest.mock('./versions', () => ({
|
||||
'@backstage/e2e-test-utils': '1.0.0',
|
||||
'@backstage/integration-react': '1.0.0',
|
||||
'@backstage/plugin-api-docs': '1.0.0',
|
||||
'@backstage/plugin-auth': '1.0.0',
|
||||
'@backstage/plugin-catalog': '1.0.0',
|
||||
'@backstage/plugin-catalog-common': '1.0.0',
|
||||
'@backstage/plugin-catalog-graph': '1.0.0',
|
||||
@@ -90,6 +91,7 @@ jest.mock('./versions', () => ({
|
||||
'@backstage/plugin-catalog-react': '1.0.0',
|
||||
'@backstage/plugin-kubernetes': '1.0.0',
|
||||
'@backstage/plugin-kubernetes-backend': '1.0.0',
|
||||
'@backstage/plugin-mcp-actions-backend': '1.0.0',
|
||||
'@backstage/plugin-notifications': '1.0.0',
|
||||
'@backstage/plugin-notifications-backend': '1.0.0',
|
||||
'@backstage/plugin-org': '1.0.0',
|
||||
|
||||
@@ -57,6 +57,7 @@ import { version as pluginApiDocs } from '../../../../plugins/api-docs/package.j
|
||||
import { version as pluginAppVisualizer } from '../../../../plugins/app-visualizer/package.json';
|
||||
import { version as pluginAppBackend } from '../../../../plugins/app-backend/package.json';
|
||||
import { version as pluginAppReact } from '../../../../plugins/app-react/package.json';
|
||||
import { version as pluginAuth } from '../../../../plugins/auth/package.json';
|
||||
import { version as pluginAuthBackend } from '../../../../plugins/auth-backend/package.json';
|
||||
import { version as pluginAuthBackendModuleGithubProvider } from '../../../../plugins/auth-backend-module-github-provider/package.json';
|
||||
import { version as pluginAuthBackendModuleGuestProvider } from '../../../../plugins/auth-backend-module-guest-provider/package.json';
|
||||
@@ -71,6 +72,7 @@ import { version as pluginCatalogGraph } from '../../../../plugins/catalog-graph
|
||||
import { version as pluginCatalogImport } from '../../../../plugins/catalog-import/package.json';
|
||||
import { version as pluginKubernetes } from '../../../../plugins/kubernetes/package.json';
|
||||
import { version as pluginKubernetesBackend } from '../../../../plugins/kubernetes-backend/package.json';
|
||||
import { version as pluginMcpActionsBackend } from '../../../../plugins/mcp-actions-backend/package.json';
|
||||
import { version as pluginNotifications } from '../../../../plugins/notifications/package.json';
|
||||
import { version as pluginNotificationsBackend } from '../../../../plugins/notifications-backend/package.json';
|
||||
import { version as pluginOrg } from '../../../../plugins/org/package.json';
|
||||
@@ -123,6 +125,7 @@ export const packageVersions = {
|
||||
'@backstage/plugin-app-backend': pluginAppBackend,
|
||||
'@backstage/plugin-app-react': pluginAppReact,
|
||||
'@backstage/plugin-app-visualizer': pluginAppVisualizer,
|
||||
'@backstage/plugin-auth': pluginAuth,
|
||||
'@backstage/plugin-auth-backend': pluginAuthBackend,
|
||||
'@backstage/plugin-auth-backend-module-github-provider':
|
||||
pluginAuthBackendModuleGithubProvider,
|
||||
@@ -141,6 +144,7 @@ export const packageVersions = {
|
||||
'@backstage/plugin-catalog-import': pluginCatalogImport,
|
||||
'@backstage/plugin-kubernetes': pluginKubernetes,
|
||||
'@backstage/plugin-kubernetes-backend': pluginKubernetesBackend,
|
||||
'@backstage/plugin-mcp-actions-backend': pluginMcpActionsBackend,
|
||||
'@backstage/plugin-notifications': pluginNotifications,
|
||||
'@backstage/plugin-notifications-backend': pluginNotificationsBackend,
|
||||
'@backstage/plugin-org': pluginOrg,
|
||||
|
||||
@@ -30,6 +30,12 @@ backend:
|
||||
database:
|
||||
client: better-sqlite3
|
||||
connection: ':memory:'
|
||||
# see https://backstage.io/docs/ai/mcp-actions#actions-configuration for more details
|
||||
actions:
|
||||
pluginSources:
|
||||
- auth
|
||||
- catalog
|
||||
- scaffolder
|
||||
# workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir
|
||||
|
||||
integrations:
|
||||
@@ -67,6 +73,18 @@ auth:
|
||||
providers:
|
||||
# See https://backstage.io/docs/auth/guest/provider
|
||||
guest: {}
|
||||
# see https://backstage.io/docs/ai/mcp-actions#client-id-metadata-documents
|
||||
# to learn more about client id metadata documents
|
||||
experimentalClientIdMetadataDocuments:
|
||||
enabled: false
|
||||
# Optional: restrict which `client_id` URLs are allowed (defaults to ['*'])
|
||||
# allowedClientIdPatterns:
|
||||
# - 'https://example.com/*'
|
||||
# - 'https://*.trusted-domain.com/*'
|
||||
# Optional: restrict which redirect URIs are allowed (defaults to ['*'])
|
||||
# allowedRedirectUriPatterns:
|
||||
# - 'http://localhost:*'
|
||||
# - 'https://*.example.com/*'
|
||||
|
||||
scaffolder:
|
||||
# see https://backstage.io/docs/features/software-templates/configuration for software template options
|
||||
@@ -111,3 +129,8 @@ kubernetes:
|
||||
permission:
|
||||
# setting this to `false` will disable permissions
|
||||
enabled: true
|
||||
|
||||
# see https://backstage.io/docs/ai/mcp-actions for more details
|
||||
mcpActions:
|
||||
name: 'My Company Backstage' # defaults to "backstage"
|
||||
description: 'Tools for managing your software catalog, creating new services from templates, and exploring your developer portal' # optional
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@backstage/plugin-catalog-backend-module-logs": "^{{version '@backstage/plugin-catalog-backend-module-logs'}}",
|
||||
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}",
|
||||
"@backstage/plugin-kubernetes-backend": "^{{version '@backstage/plugin-kubernetes-backend'}}",
|
||||
"@backstage/plugin-mcp-actions-backend": "^{{version '@backstage/plugin-mcp-actions-backend'}}",
|
||||
"@backstage/plugin-notifications-backend": "^{{version '@backstage/plugin-notifications-backend'}}",
|
||||
"@backstage/plugin-permission-backend": "^{{version '@backstage/plugin-permission-backend'}}",
|
||||
"@backstage/plugin-permission-backend-module-allow-all-policy": "^{{version '@backstage/plugin-permission-backend-module-allow-all-policy'}}",
|
||||
|
||||
@@ -63,4 +63,7 @@ backend.add(import('@backstage/plugin-kubernetes-backend'));
|
||||
backend.add(import('@backstage/plugin-notifications-backend'));
|
||||
backend.add(import('@backstage/plugin-signals-backend'));
|
||||
|
||||
// mcp actions plugin
|
||||
backend.add(import('@backstage/plugin-mcp-actions-backend'));
|
||||
|
||||
backend.start();
|
||||
|
||||
@@ -39,6 +39,12 @@ backend:
|
||||
database:
|
||||
client: better-sqlite3
|
||||
connection: ':memory:'
|
||||
# see https://backstage.io/docs/ai/mcp-actions#actions-configuration for more details
|
||||
actions:
|
||||
pluginSources:
|
||||
- auth
|
||||
- catalog
|
||||
- scaffolder
|
||||
# workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir
|
||||
|
||||
integrations:
|
||||
@@ -76,6 +82,25 @@ auth:
|
||||
providers:
|
||||
# See https://backstage.io/docs/auth/guest/provider
|
||||
guest: {}
|
||||
# see https://backstage.io/docs/ai/mcp-actions#dynamic-client-registration
|
||||
# to learn more about dynamic client registration
|
||||
experimentalDynamicClientRegistration:
|
||||
enabled: false
|
||||
# Optional: limit valid callback URLs for added security
|
||||
# allowedRedirectUriPatterns:
|
||||
# - cursor://*
|
||||
# see https://backstage.io/docs/ai/mcp-actions#client-id-metadata-documents
|
||||
# to learn more about client id metadata documents
|
||||
experimentalClientIdMetadataDocuments:
|
||||
enabled: true
|
||||
# Optional: restrict which `client_id` URLs are allowed (defaults to ['*'])
|
||||
# allowedClientIdPatterns:
|
||||
# - 'https://example.com/*'
|
||||
# - 'https://*.trusted-domain.com/*'
|
||||
# Optional: restrict which redirect URIs are allowed (defaults to ['*'])
|
||||
# allowedRedirectUriPatterns:
|
||||
# - 'http://localhost:*'
|
||||
# - 'https://*.example.com/*'
|
||||
|
||||
scaffolder:
|
||||
# see https://backstage.io/docs/features/software-templates/configuration for software template options
|
||||
@@ -120,3 +145,8 @@ kubernetes:
|
||||
permission:
|
||||
# setting this to `false` will disable permissions
|
||||
enabled: true
|
||||
|
||||
# see https://backstage.io/docs/ai/mcp-actions for more details
|
||||
mcpActions:
|
||||
name: 'My Company Backstage' # defaults to "backstage"
|
||||
description: 'Tools for managing your software catalog, creating new services from templates, and exploring your developer portal' # optional
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@backstage/plugin-api-docs": "^{{ version '@backstage/plugin-api-docs'}}",
|
||||
"@backstage/plugin-app-react": "^{{ version '@backstage/plugin-app-react'}}",
|
||||
"@backstage/plugin-app-visualizer": "^{{ version '@backstage/plugin-app-visualizer'}}",
|
||||
"@backstage/plugin-auth": "^{{ version '@backstage/plugin-auth'}}",
|
||||
"@backstage/plugin-catalog": "^{{ version '@backstage/plugin-catalog'}}",
|
||||
"@backstage/plugin-catalog-graph": "^{{ version '@backstage/plugin-catalog-graph'}}",
|
||||
"@backstage/plugin-catalog-import": "^{{ version '@backstage/plugin-catalog-import'}}",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@backstage/plugin-catalog-backend-module-logs": "^{{version '@backstage/plugin-catalog-backend-module-logs'}}",
|
||||
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}",
|
||||
"@backstage/plugin-kubernetes-backend": "^{{version '@backstage/plugin-kubernetes-backend'}}",
|
||||
"@backstage/plugin-mcp-actions-backend": "^{{version '@backstage/plugin-mcp-actions-backend'}}",
|
||||
"@backstage/plugin-notifications-backend": "^{{version '@backstage/plugin-notifications-backend'}}",
|
||||
"@backstage/plugin-permission-backend": "^{{version '@backstage/plugin-permission-backend'}}",
|
||||
"@backstage/plugin-permission-backend-module-allow-all-policy": "^{{version '@backstage/plugin-permission-backend-module-allow-all-policy'}}",
|
||||
|
||||
@@ -63,4 +63,7 @@ backend.add(import('@backstage/plugin-kubernetes-backend'));
|
||||
backend.add(import('@backstage/plugin-notifications-backend'));
|
||||
backend.add(import('@backstage/plugin-signals-backend'));
|
||||
|
||||
// mcp actions plugin
|
||||
backend.add(import('@backstage/plugin-mcp-actions-backend'));
|
||||
|
||||
backend.start();
|
||||
|
||||
Reference in New Issue
Block a user