@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend
2
2
 
3
+ ## 3.1.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 94e2278: Refactor the MCP server configure modal with PatternFly layout and improved credential management:
8
+
9
+ - Add **Use organization default token** / **Use personal token** radio selectors when an app-config default token is available, replacing the remove-personal-token flow
10
+ - Show server status, tools list, and enabled toggle with local draft state applied on Save
11
+ - Hide the tools section when the server is disabled; keep status consistent while drafting an unverified personal token
12
+ - Disable Save after a failed token validation until the input changes
13
+ - Auto-enable the server after a successful personal token save
14
+ - Add sortable **Name** and **Status** columns to the MCP servers table, with always-visible sort icons (gray when inactive, directional when active)
15
+ - Keep the DCR configure modal aligned with personal-token servers (status, tools, enabled toggle, and Save/Cancel) with an additional DCR info alert and no token input
16
+ - Show **Fetching status...** in the Status section while server tools/status are loading
17
+ - Bump `@patternfly/react-core` to 6.6.0 and add translations for new modal strings (de, es, fr, it, ja)
18
+
19
+ The backend now exposes `hasOrgToken` on MCP server list and patch responses so the UI can distinguish organization default tokens from personal-only servers.
20
+ - @red-hat-developer-hub/backstage-plugin-intelligent-assistant-common@3.1.0
21
+
22
+ ## 3.0.3
23
+
24
+ ### Patch Changes
25
+
26
+ - @red-hat-developer-hub/backstage-plugin-intelligent-assistant-common@3.0.3
27
+
3
28
  ## 3.0.2
4
29
 
5
30
  ### Patch Changes
package/README.md CHANGED
@@ -254,6 +254,77 @@ settings panel:
254
254
  These endpoints power server selection and token configuration, including inline
255
255
  success/error feedback while users enter tokens.
256
256
 
257
+ #### DCR authentication for Backstage-internal MCP servers (optional)
258
+
259
+ By default, MCP servers use **static tokens** (`token` in app-config or a personal
260
+ token in the UI). For Backstage-internal MCP servers that support OAuth, you can
261
+ instead use **Dynamic Client Registration (DCR)**: Lightspeed mints a per-user
262
+ Backstage plugin-request token on each request — no manual token is required.
263
+
264
+ DCR is **not enabled out of the box**. Adopters must configure the Backstage
265
+ instance, Lightspeed Core (LCS), and Lightspeed app-config as follows.
266
+
267
+ **1. Backstage backend** — register the MCP actions plugin in
268
+ `packages/backend/src/index.ts` and add the dependency (pin version **0.1.12**;
269
+ do not use `^0.1.14` with `backend-defaults@0.16` — the plugin will fail to start):
270
+
271
+ ```bash
272
+ yarn add --cwd packages/backend @backstage/plugin-mcp-actions-backend@0.1.12
273
+ ```
274
+
275
+ ```ts
276
+ backend.add(import('@backstage/plugin-mcp-actions-backend'));
277
+ ```
278
+
279
+ Expose catalog/scaffolder actions as MCP tools (adjust plugin IDs for your setup):
280
+
281
+ ```yaml
282
+ backend:
283
+ actions:
284
+ pluginSources:
285
+ - catalog
286
+ - scaffolder
287
+ ```
288
+
289
+ **2. Backstage auth** — enable experimental DCR and use the new frontend app
290
+ (`@backstage/plugin-auth` is required for the OAuth consent flow; `yarn start`,
291
+ not `start:legacy`):
292
+
293
+ ```yaml
294
+ auth:
295
+ experimentalDynamicClientRegistration:
296
+ enabled: true
297
+ allowedRedirectUriPatterns:
298
+ - '*'
299
+ ```
300
+
301
+ **3. Lightspeed app-config** — mark the MCP server as DCR (omit `token`; it is
302
+ ignored when `auth: dcr` is set):
303
+
304
+ ```yaml
305
+ intelligent-assistant:
306
+ mcpServers:
307
+ - name: test-mcp-server
308
+ auth: dcr
309
+ ```
310
+
311
+ **4. LCS (`lightspeed-stack.yaml`)** — point the server URL at your Backstage
312
+ MCP endpoint and use client authorization headers:
313
+
314
+ ```yaml
315
+ mcp_servers:
316
+ - name: test-mcp-server
317
+ url: 'http://<backstage-host>:7007/api/mcp-actions/v1'
318
+ authorization_headers:
319
+ Authorization: client
320
+ ```
321
+
322
+ **5. MCP clients (e.g. Cursor)** — connect to the same Backstage MCP URL. DCR
323
+ handles OAuth; no static token in `mcp.json` is needed when DCR is configured.
324
+
325
+ See also commented examples in the workspace `app-config.yaml` under
326
+ `intelligent-assistant.mcpServers` and `auth.experimentalDynamicClientRegistration`.
327
+
257
328
  #### Permission Framework Support
258
329
 
259
330
  The Intelligent Assistant Backend plugin has support for the permission framework.
package/dist/index.d.ts CHANGED
@@ -50,6 +50,8 @@ interface McpServerResponse {
50
50
  toolCount: number;
51
51
  hasToken: boolean;
52
52
  hasUserToken: boolean;
53
+ /** True when app-config defines a default token for this server. */
54
+ hasOrgToken: boolean;
53
55
  /** Authentication mode — `'dcr'` means tokens are minted automatically. */
54
56
  auth?: McpServerAuth;
55
57
  }
@@ -189,6 +189,7 @@ async function createRouter(options) {
189
189
  // DCR servers always have a token (minted per-request); static servers check DB + config.
190
190
  hasToken: server.auth === "dcr" || !!(setting?.token || server.token),
191
191
  hasUserToken: !!setting?.token,
192
+ hasOrgToken: server.auth !== "dcr" && !!server.token,
192
193
  auth: server.auth
193
194
  };
194
195
  });
@@ -363,6 +364,7 @@ async function createRouter(options) {
363
364
  toolCount: setting.tool_count,
364
365
  hasToken: server.auth === "dcr" || !!(setting.token || server.token),
365
366
  hasUserToken: !!setting.token,
367
+ hasOrgToken: server.auth !== "dcr" && !!server.token,
366
368
  auth: server.auth
367
369
  }
368
370
  };
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport type { BasicPermission } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport express, { Router } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nimport {\n lightspeedChatCreatePermission,\n lightspeedChatDeletePermission,\n lightspeedChatReadPermission,\n lightspeedMcpManagePermission,\n lightspeedMcpReadPermission,\n lightspeedPermissions,\n} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { Readable } from 'node:stream';\n\nimport {\n DEFAULT_LIGHTSPEED_SERVICE_HOST,\n DEFAULT_LIGHTSPEED_SERVICE_PORT,\n EXPRESS_JSON_BODY_LIMIT,\n} from './constant';\nimport { McpUserSettingsStore } from './mcp-server-store';\nimport {\n McpServerAuth,\n McpServerResponse,\n McpServerStatus,\n McpValidationResult,\n} from './mcp-server-types';\nimport { McpServerValidator } from './mcp-server-validator';\nimport { createPermissionMiddleware } from './middleware/createPermissionMiddleware';\nimport { createRateLimitMiddleware } from './middleware/createRateLimitMiddleware';\nimport {\n createIdentityMiddleware,\n getIdentity,\n} from './middleware/getIdentity';\nimport { VectorStoresOperator } from './notebooks/VectorStoresOperator';\nimport { userPermissionAuthorization } from './permission';\nimport { createTokenEncryptor } from './token-encryption';\nimport { QueryRequestBody, RouterOptions } from './types';\nimport { handleLCSFetchError, rewriteProxyPath } from './utils';\nimport { validateCompletionsRequest } from './validation';\n\n/**\n * MCP Server authentication modes for lightspeed.mcpServers entries.\n *\n * - `'dcr'` — Dynamic Client Registration. The Lightspeed backend mints a\n * short-lived Backstage plugin-request token carrying the current user's\n * identity. This token is forwarded to the MCP server via LCORE's\n * MCP-HEADERS, and the MCP Actions backend validates it against the\n * Backstage Permission Framework (RBAC). Use this for Backstage-internal\n * MCP servers (e.g. `@backstage/plugin-mcp-actions-backend`).\n * A static `token` field is **ignored** when `auth: dcr` is set.\n *\n * - (absent / undefined) — Legacy static-token mode. The token is resolved\n * from the user's DB override first, then from the `token` field in\n * app-config. If neither exists, the server is omitted from MCP-HEADERS.\n * Users can also set their own tokens via the Lightspeed UI.\n */\ninterface StaticMcpServer {\n name: string;\n token?: string;\n auth?: McpServerAuth;\n}\n\n/**\n * Build MCP-HEADERS for LCS. Format matches the LCS \"client\"/\"oauth\" auth\n * model: `{ \"server-name\": { \"Authorization\": \"<token>\" } }`\n *\n * For each admin-configured server:\n *\n * 1. If `auth: 'dcr'`, a Backstage plugin-request token is minted on behalf\n * of the authenticated user. Any static token is ignored.\n *\n * 2. Otherwise, the user's personal token (DB) takes precedence over the\n * admin default from app-config. If neither exists, the server is\n * excluded from MCP-HEADERS (LCORE will skip it or return 401).\n *\n * Servers the user has disabled are always excluded.\n */\nasync function buildMcpHeaders(\n servers: StaticMcpServer[],\n store: McpUserSettingsStore,\n userEntityRef: string,\n options?: {\n dcrAuth?: { authService: AuthService; credentials: BackstageCredentials };\n logger?: LoggerService;\n },\n): Promise<string> {\n const headers: Record<string, { Authorization: string }> = {};\n const userSettings = await store.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n for (const server of servers) {\n const setting = settingsMap.get(server.name);\n const enabled = setting ? Boolean(setting.enabled) : true;\n if (!enabled) continue;\n\n if (server.auth === 'dcr') {\n if (options?.dcrAuth) {\n try {\n const { token } =\n await options.dcrAuth.authService.getPluginRequestToken({\n onBehalfOf: options.dcrAuth.credentials,\n targetPluginId: 'mcp-actions',\n });\n headers[server.name] = { Authorization: `${token}` };\n } catch (err) {\n options?.logger?.error(\n `Failed to mint DCR token for MCP server '${server.name}': ${err}`,\n );\n }\n } else {\n options?.logger?.warn(\n `MCP server '${server.name}' has auth: dcr but AuthService is not available; skipping`,\n );\n }\n } else {\n // Static token: user's personal token (DB) > admin default (app-config).\n // If neither exists, the server is excluded from MCP-HEADERS.\n const token = setting?.token || server.token;\n if (token) {\n headers[server.name] = { Authorization: `${token}` };\n }\n }\n }\n\n return Object.keys(headers).length > 0 ? JSON.stringify(headers) : '';\n}\n\n/**\n * @public\n * The lightspeed backend router\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, database, httpAuth, auth, userInfo, permissions } =\n options;\n\n const router = Router();\n router.use(express.json());\n\n const port =\n config.getOptionalNumber('intelligent-assistant.servicePort') ??\n DEFAULT_LIGHTSPEED_SERVICE_PORT;\n const system_prompt = config.getOptionalString(\n 'intelligent-assistant.systemPrompt',\n );\n const lcsBaseUrl = `http://${DEFAULT_LIGHTSPEED_SERVICE_HOST}:${port}`;\n\n const apiProxy = createProxyMiddleware({\n target: lcsBaseUrl,\n changeOrigin: true,\n pathRewrite: (path, req) => {\n const userEntityRef = (req as any).userEntityRef;\n const newPath = rewriteProxyPath(path, userEntityRef);\n\n if (newPath !== path) {\n logger.info(`Rewriting path from ${path} to ${newPath}`);\n }\n return newPath;\n },\n });\n\n const vectorStoresOperator = VectorStoresOperator.getInstance(\n lcsBaseUrl,\n logger,\n );\n // Parse admin-configured MCP servers from app-config.\n //\n // Each entry supports:\n // name (required) — unique identifier, must match the name in lightspeed-stack.yaml\n // auth (optional) — authentication mode:\n // 'dcr' = the backend mints a per-user Backstage token (for\n // Backstage-internal MCP servers with DCR/OAuth enabled)\n // absent = legacy static-token mode (see `token` below)\n // token (optional) — static fallback token from app-config. Ignored when auth: dcr.\n // Users can also set personal tokens via the Lightspeed UI.\n //\n // URLs come from LCS (GET /v1/mcp-servers), not from app-config.\n const mcpServersConfig = config.getOptionalConfigArray(\n 'intelligent-assistant.mcpServers',\n );\n const staticServers: StaticMcpServer[] = [];\n if (mcpServersConfig) {\n for (const mcpServer of mcpServersConfig) {\n const authValue = mcpServer.getOptionalString('auth')?.toLowerCase();\n if (authValue && authValue !== 'dcr') {\n logger.warn(\n `MCP server '${mcpServer.getString('name')}' has unsupported auth value '${authValue}'; ` +\n `only 'dcr' is supported — falling back to static-token mode`,\n );\n }\n staticServers.push({\n name: mcpServer.getString('name'),\n token: mcpServer.getOptionalString('token'),\n auth: authValue === 'dcr' ? 'dcr' : undefined,\n });\n }\n }\n\n // Initialize database-backed store for per-user preferences and validator\n const dbClient = await database.getClient();\n const encryptor = createTokenEncryptor(config, logger);\n const settingsStore = new McpUserSettingsStore(dbClient, encryptor, logger);\n const mcpValidator = new McpServerValidator(logger);\n\n // URL cache populated from LCS GET /v1/mcp-servers.\n // The canonical URL for each MCP server lives in LCS config, not app-config.\n const lcsUrlCache = new Map<string, string>();\n\n async function refreshLcsUrlCache(): Promise<void> {\n try {\n const response = await fetch(`${lcsBaseUrl}/v1/mcp-servers`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n logger.warn(\n `Failed to fetch MCP server URLs from LCS: HTTP ${response.status}`,\n );\n return;\n }\n const data = (await response.json()) as {\n servers: Array<{ name: string; url: string }>;\n };\n for (const s of data.servers) {\n lcsUrlCache.set(s.name, s.url);\n }\n logger.info(`Cached ${lcsUrlCache.size} MCP server URL(s) from LCS`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn(`Failed to fetch MCP server URLs from LCS: ${msg}`);\n }\n }\n\n function resolveServerUrl(serverName: string): string | undefined {\n return lcsUrlCache.get(serverName);\n }\n\n // Best-effort URL cache on startup (non-blocking)\n refreshLcsUrlCache().catch(() => {});\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n permissions: lightspeedPermissions,\n });\n router.use(permissionIntegrationRouter);\n\n const identityMiddleware = createIdentityMiddleware(\n httpAuth,\n userInfo,\n logger,\n );\n router.use((req, res, next) => {\n // Middleware mounts to notebooks router independently\n // so we skip it here\n if (req.path.startsWith('/notebooks')) {\n return next();\n }\n return identityMiddleware(req, res, next);\n });\n\n const authorizer = userPermissionAuthorization(permissions);\n\n function requirePermission(permission: BasicPermission) {\n return createPermissionMiddleware(authorizer, permission, logger);\n }\n\n const expensiveRateLimiter = createRateLimitMiddleware(\n config,\n 'expensive',\n logger,\n );\n const generalRateLimiter = createRateLimitMiddleware(\n config,\n 'general',\n logger,\n );\n\n // ─── MCP Server Management Endpoints ────────────────────────────────\n // All MCP servers are admin-configured (static). Users can view the\n // list, toggle servers on/off, and provide personal access tokens.\n\n router.get(\n '/mcp-servers',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const userSettings = await settingsStore.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n const hasAllUrls = staticServers.every(s => lcsUrlCache.has(s.name));\n if (!hasAllUrls) {\n await refreshLcsUrlCache();\n }\n\n const servers: McpServerResponse[] = staticServers.map(server => {\n const setting = settingsMap.get(server.name);\n return {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: setting ? Boolean(setting.enabled) : true,\n status: setting?.status ?? 'unknown',\n toolCount: setting?.tool_count ?? 0,\n // DCR servers always have a token (minted per-request); static servers check DB + config.\n hasToken:\n server.auth === 'dcr' || !!(setting?.token || server.token),\n hasUserToken: !!setting?.token,\n auth: server.auth,\n };\n });\n\n res.json({ servers });\n } catch (error) {\n logger.error(`Error listing MCP servers: ${error}`);\n res.status(500).json({ error: 'Failed to list MCP servers' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { url, token } = req.body;\n if (!url || !token) {\n res.status(400).json({ error: 'url and token are required' });\n return;\n }\n\n // SSRF protection: only allow URLs registered in LCS\n let knownUrls = new Set(lcsUrlCache.values());\n if (!knownUrls.has(url)) {\n await refreshLcsUrlCache();\n knownUrls = new Set(lcsUrlCache.values());\n }\n if (!knownUrls.has(url)) {\n res.status(400).json({\n error:\n 'URL not recognized — only MCP server URLs registered in LCS are allowed',\n });\n return;\n }\n\n const result = await mcpValidator.validate(url, token);\n res.json(result);\n } catch (error) {\n logger.error(`Error validating MCP credentials: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/:name/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef, credentials } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n // Resolve URL: LCS cache → fresh LCS fetch\n let serverUrl = resolveServerUrl(server.name);\n if (!serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (!serverUrl) {\n res\n .status(400)\n .json({ error: 'Server has no URL — not found in LCS or config' });\n return;\n }\n\n let effectiveToken: string | undefined;\n if (server.auth === 'dcr') {\n try {\n const { token: dcrToken } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'mcp-actions',\n });\n effectiveToken = dcrToken;\n } catch (err) {\n logger.error(\n `Failed to mint DCR token for server '${name}': ${err}`,\n );\n res.status(502).json({\n error: `Failed to mint authentication token for DCR server '${name}' — check Backstage auth configuration`,\n });\n return;\n }\n } else {\n const setting = await settingsStore.get(name, userEntityRef);\n effectiveToken = setting?.token || server.token;\n }\n if (!effectiveToken) {\n res\n .status(400)\n .json({ error: 'No token available — provide one first' });\n return;\n }\n\n const validation = await mcpValidator.validate(\n serverUrl,\n effectiveToken,\n );\n const status: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n status,\n validation.toolCount,\n );\n\n res.json({\n name,\n status,\n toolCount: validation.toolCount,\n validation,\n });\n } catch (error) {\n logger.error(`Error validating MCP server: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.patch(\n '/mcp-servers/:name',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n\n const body = (req.body ?? {}) as {\n enabled?: boolean;\n token?: string | null;\n };\n const hasEnabledField = Object.prototype.hasOwnProperty.call(\n body,\n 'enabled',\n );\n const hasTokenField = Object.prototype.hasOwnProperty.call(\n body,\n 'token',\n );\n const { enabled, token } = body;\n if (!hasEnabledField && !hasTokenField) {\n res.status(400).json({\n error: 'At least one of enabled or token must be provided',\n });\n return;\n }\n\n const setting = await settingsStore.upsert(name, userEntityRef, {\n enabled: hasEnabledField ? enabled : undefined,\n token: hasTokenField ? token : undefined,\n });\n\n let validation: McpValidationResult | undefined;\n let serverUrl = resolveServerUrl(server.name);\n if (token && !serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (token && serverUrl) {\n validation = await mcpValidator.validate(serverUrl, token);\n const newStatus: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n newStatus,\n validation.toolCount,\n );\n setting.status = newStatus;\n setting.tool_count = validation.toolCount;\n }\n\n const result: Record<string, unknown> = {\n server: {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: Boolean(setting.enabled),\n status: setting.status,\n toolCount: setting.tool_count,\n hasToken:\n server.auth === 'dcr' || !!(setting.token || server.token),\n hasUserToken: !!setting.token,\n auth: server.auth,\n },\n };\n if (validation) result.validation = validation;\n res.json(result);\n } catch (error) {\n logger.error(`Error updating MCP server settings: ${error}`);\n res.status(500).json({ error: 'Failed to update MCP server settings' });\n }\n },\n );\n\n // Returns conversation IDs associated with notebook sessions for filtering\n router.get(\n '/notebook-conversation-ids',\n generalRateLimiter,\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const vectorStoresPage = await vectorStoresOperator.vectorStores.list();\n const vectorStores = vectorStoresPage.data || [];\n\n const conversationIds: string[] = [];\n\n for (const store of vectorStores) {\n const sessionUserId = store.metadata?.user_id as string;\n const conversationId = store.metadata?.conversation_id as\n | string\n | null;\n\n // Only include this user's sessions with a conversation_id\n if (sessionUserId === userEntityRef && conversationId) {\n conversationIds.push(conversationId);\n }\n }\n\n res.json({\n conversation_ids: conversationIds,\n });\n } catch (error) {\n const errormsg = `Error fetching notebook conversation IDs: ${error}`;\n logger.error(errormsg);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: errormsg });\n }\n }\n },\n );\n\n // ─── Proxy Routes ───────────────────────────────────────────────────\n\n router.get(\n '/v1/models',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v1/shields',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.delete(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatDeletePermission),\n apiProxy,\n );\n router.get(\n '/v1/feedback/status',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n\n router.post(\n '/v1/feedback',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(`/v1/feedback receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/feedback?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'sending feedback',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while sending feedback: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query/interrupt',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query/interrupt?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'interrupting query',\n response,\n );\n return;\n }\n response.status(fetchResponse.status).json(await fetchResponse.json());\n } catch (error) {\n const errormsg = `Error while interrupting query: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query',\n express.json({ limit: EXPRESS_JSON_BODY_LIMIT }),\n expensiveRateLimiter,\n validateCompletionsRequest,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n const { provider }: Pick<QueryRequestBody, 'provider'> = request.body;\n try {\n const { userEntityRef, credentials } = getIdentity(request);\n\n logger.info(`/v1/query receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n request.body.media_type = 'application/json'; // set media_type to receive start and end event\n // if system_prompt is defined in lightspeed config\n // set system_prompt to override the default rhdh system prompt\n if (system_prompt && system_prompt.trim().length > 0) {\n request.body.system_prompt = system_prompt;\n }\n\n const requestBody = JSON.stringify(request.body);\n\n // Build MCP headers from config servers + this user's preferences.\n // For servers with auth: dcr, a per-user Backstage token is minted.\n const mcpHeadersValue = await buildMcpHeaders(\n staticServers,\n settingsStore,\n userEntityRef,\n { dcrAuth: { authService: auth, credentials }, logger },\n );\n\n const abortController = new AbortController();\n\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'MCP-HEADERS': mcpHeadersValue,\n },\n body: requestBody,\n signal: abortController.signal,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'processing query',\n response,\n );\n return;\n }\n\n // Pipe the response back to the original response\n if (fetchResponse.body) {\n const nodeStream = Readable.fromWeb(fetchResponse.body as any);\n\n nodeStream.on('error', (error: Error) => {\n logger.error(\n `Upstream stream error while processing query: ${error}`,\n );\n if (response.headersSent) {\n response.destroy();\n } else {\n response.status(500).json({ error: 'Stream error occurred' });\n }\n abortController.abort();\n });\n\n response.on('close', () => {\n if (!response.writableFinished) {\n logger.warn('Client disconnected while processing query');\n nodeStream.destroy();\n abortController.abort();\n }\n });\n\n nodeStream.pipe(response);\n }\n } catch (error) {\n const errormsg = `Error fetching completions from ${provider}: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.put(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const conversation_id = request.params.conversation_id;\n\n const requestBody = JSON.stringify(request.body);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v2/conversations/${conversation_id}?${userQueryParam}`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'updating conversation',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while updating topic summary: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.use((_request, response) => {\n response.status(404).json({ error: 'Requested path is not available' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","DEFAULT_LIGHTSPEED_SERVICE_PORT","DEFAULT_LIGHTSPEED_SERVICE_HOST","createProxyMiddleware","rewriteProxyPath","VectorStoresOperator","createTokenEncryptor","McpUserSettingsStore","McpServerValidator","createPermissionIntegrationRouter","lightspeedPermissions","createIdentityMiddleware","userPermissionAuthorization","createPermissionMiddleware","createRateLimitMiddleware","lightspeedMcpReadPermission","getIdentity","lightspeedMcpManagePermission","NotAllowedError","lightspeedChatReadPermission","lightspeedChatDeletePermission","lightspeedChatCreatePermission","handleLCSFetchError","EXPRESS_JSON_BODY_LIMIT","validateCompletionsRequest","Readable","MiddlewareFactory"],"mappings":"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"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport type { BasicPermission } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport express, { Router } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nimport {\n lightspeedChatCreatePermission,\n lightspeedChatDeletePermission,\n lightspeedChatReadPermission,\n lightspeedMcpManagePermission,\n lightspeedMcpReadPermission,\n lightspeedPermissions,\n} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { Readable } from 'node:stream';\n\nimport {\n DEFAULT_LIGHTSPEED_SERVICE_HOST,\n DEFAULT_LIGHTSPEED_SERVICE_PORT,\n EXPRESS_JSON_BODY_LIMIT,\n} from './constant';\nimport { McpUserSettingsStore } from './mcp-server-store';\nimport {\n McpServerAuth,\n McpServerResponse,\n McpServerStatus,\n McpValidationResult,\n} from './mcp-server-types';\nimport { McpServerValidator } from './mcp-server-validator';\nimport { createPermissionMiddleware } from './middleware/createPermissionMiddleware';\nimport { createRateLimitMiddleware } from './middleware/createRateLimitMiddleware';\nimport {\n createIdentityMiddleware,\n getIdentity,\n} from './middleware/getIdentity';\nimport { VectorStoresOperator } from './notebooks/VectorStoresOperator';\nimport { userPermissionAuthorization } from './permission';\nimport { createTokenEncryptor } from './token-encryption';\nimport { QueryRequestBody, RouterOptions } from './types';\nimport { handleLCSFetchError, rewriteProxyPath } from './utils';\nimport { validateCompletionsRequest } from './validation';\n\n/**\n * MCP Server authentication modes for lightspeed.mcpServers entries.\n *\n * - `'dcr'` — Dynamic Client Registration. The Lightspeed backend mints a\n * short-lived Backstage plugin-request token carrying the current user's\n * identity. This token is forwarded to the MCP server via LCORE's\n * MCP-HEADERS, and the MCP Actions backend validates it against the\n * Backstage Permission Framework (RBAC). Use this for Backstage-internal\n * MCP servers (e.g. `@backstage/plugin-mcp-actions-backend`).\n * A static `token` field is **ignored** when `auth: dcr` is set.\n *\n * - (absent / undefined) — Legacy static-token mode. The token is resolved\n * from the user's DB override first, then from the `token` field in\n * app-config. If neither exists, the server is omitted from MCP-HEADERS.\n * Users can also set their own tokens via the Lightspeed UI.\n */\ninterface StaticMcpServer {\n name: string;\n token?: string;\n auth?: McpServerAuth;\n}\n\n/**\n * Build MCP-HEADERS for LCS. Format matches the LCS \"client\"/\"oauth\" auth\n * model: `{ \"server-name\": { \"Authorization\": \"<token>\" } }`\n *\n * For each admin-configured server:\n *\n * 1. If `auth: 'dcr'`, a Backstage plugin-request token is minted on behalf\n * of the authenticated user. Any static token is ignored.\n *\n * 2. Otherwise, the user's personal token (DB) takes precedence over the\n * admin default from app-config. If neither exists, the server is\n * excluded from MCP-HEADERS (LCORE will skip it or return 401).\n *\n * Servers the user has disabled are always excluded.\n */\nasync function buildMcpHeaders(\n servers: StaticMcpServer[],\n store: McpUserSettingsStore,\n userEntityRef: string,\n options?: {\n dcrAuth?: { authService: AuthService; credentials: BackstageCredentials };\n logger?: LoggerService;\n },\n): Promise<string> {\n const headers: Record<string, { Authorization: string }> = {};\n const userSettings = await store.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n for (const server of servers) {\n const setting = settingsMap.get(server.name);\n const enabled = setting ? Boolean(setting.enabled) : true;\n if (!enabled) continue;\n\n if (server.auth === 'dcr') {\n if (options?.dcrAuth) {\n try {\n const { token } =\n await options.dcrAuth.authService.getPluginRequestToken({\n onBehalfOf: options.dcrAuth.credentials,\n targetPluginId: 'mcp-actions',\n });\n headers[server.name] = { Authorization: `${token}` };\n } catch (err) {\n options?.logger?.error(\n `Failed to mint DCR token for MCP server '${server.name}': ${err}`,\n );\n }\n } else {\n options?.logger?.warn(\n `MCP server '${server.name}' has auth: dcr but AuthService is not available; skipping`,\n );\n }\n } else {\n // Static token: user's personal token (DB) > admin default (app-config).\n // If neither exists, the server is excluded from MCP-HEADERS.\n const token = setting?.token || server.token;\n if (token) {\n headers[server.name] = { Authorization: `${token}` };\n }\n }\n }\n\n return Object.keys(headers).length > 0 ? JSON.stringify(headers) : '';\n}\n\n/**\n * @public\n * The lightspeed backend router\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, database, httpAuth, auth, userInfo, permissions } =\n options;\n\n const router = Router();\n router.use(express.json());\n\n const port =\n config.getOptionalNumber('intelligent-assistant.servicePort') ??\n DEFAULT_LIGHTSPEED_SERVICE_PORT;\n const system_prompt = config.getOptionalString(\n 'intelligent-assistant.systemPrompt',\n );\n const lcsBaseUrl = `http://${DEFAULT_LIGHTSPEED_SERVICE_HOST}:${port}`;\n\n const apiProxy = createProxyMiddleware({\n target: lcsBaseUrl,\n changeOrigin: true,\n pathRewrite: (path, req) => {\n const userEntityRef = (req as any).userEntityRef;\n const newPath = rewriteProxyPath(path, userEntityRef);\n\n if (newPath !== path) {\n logger.info(`Rewriting path from ${path} to ${newPath}`);\n }\n return newPath;\n },\n });\n\n const vectorStoresOperator = VectorStoresOperator.getInstance(\n lcsBaseUrl,\n logger,\n );\n // Parse admin-configured MCP servers from app-config.\n //\n // Each entry supports:\n // name (required) — unique identifier, must match the name in lightspeed-stack.yaml\n // auth (optional) — authentication mode:\n // 'dcr' = the backend mints a per-user Backstage token (for\n // Backstage-internal MCP servers with DCR/OAuth enabled)\n // absent = legacy static-token mode (see `token` below)\n // token (optional) — static fallback token from app-config. Ignored when auth: dcr.\n // Users can also set personal tokens via the Lightspeed UI.\n //\n // URLs come from LCS (GET /v1/mcp-servers), not from app-config.\n const mcpServersConfig = config.getOptionalConfigArray(\n 'intelligent-assistant.mcpServers',\n );\n const staticServers: StaticMcpServer[] = [];\n if (mcpServersConfig) {\n for (const mcpServer of mcpServersConfig) {\n const authValue = mcpServer.getOptionalString('auth')?.toLowerCase();\n if (authValue && authValue !== 'dcr') {\n logger.warn(\n `MCP server '${mcpServer.getString('name')}' has unsupported auth value '${authValue}'; ` +\n `only 'dcr' is supported — falling back to static-token mode`,\n );\n }\n staticServers.push({\n name: mcpServer.getString('name'),\n token: mcpServer.getOptionalString('token'),\n auth: authValue === 'dcr' ? 'dcr' : undefined,\n });\n }\n }\n\n // Initialize database-backed store for per-user preferences and validator\n const dbClient = await database.getClient();\n const encryptor = createTokenEncryptor(config, logger);\n const settingsStore = new McpUserSettingsStore(dbClient, encryptor, logger);\n const mcpValidator = new McpServerValidator(logger);\n\n // URL cache populated from LCS GET /v1/mcp-servers.\n // The canonical URL for each MCP server lives in LCS config, not app-config.\n const lcsUrlCache = new Map<string, string>();\n\n async function refreshLcsUrlCache(): Promise<void> {\n try {\n const response = await fetch(`${lcsBaseUrl}/v1/mcp-servers`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n logger.warn(\n `Failed to fetch MCP server URLs from LCS: HTTP ${response.status}`,\n );\n return;\n }\n const data = (await response.json()) as {\n servers: Array<{ name: string; url: string }>;\n };\n for (const s of data.servers) {\n lcsUrlCache.set(s.name, s.url);\n }\n logger.info(`Cached ${lcsUrlCache.size} MCP server URL(s) from LCS`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn(`Failed to fetch MCP server URLs from LCS: ${msg}`);\n }\n }\n\n function resolveServerUrl(serverName: string): string | undefined {\n return lcsUrlCache.get(serverName);\n }\n\n // Best-effort URL cache on startup (non-blocking)\n refreshLcsUrlCache().catch(() => {});\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n permissions: lightspeedPermissions,\n });\n router.use(permissionIntegrationRouter);\n\n const identityMiddleware = createIdentityMiddleware(\n httpAuth,\n userInfo,\n logger,\n );\n router.use((req, res, next) => {\n // Middleware mounts to notebooks router independently\n // so we skip it here\n if (req.path.startsWith('/notebooks')) {\n return next();\n }\n return identityMiddleware(req, res, next);\n });\n\n const authorizer = userPermissionAuthorization(permissions);\n\n function requirePermission(permission: BasicPermission) {\n return createPermissionMiddleware(authorizer, permission, logger);\n }\n\n const expensiveRateLimiter = createRateLimitMiddleware(\n config,\n 'expensive',\n logger,\n );\n const generalRateLimiter = createRateLimitMiddleware(\n config,\n 'general',\n logger,\n );\n\n // ─── MCP Server Management Endpoints ────────────────────────────────\n // All MCP servers are admin-configured (static). Users can view the\n // list, toggle servers on/off, and provide personal access tokens.\n\n router.get(\n '/mcp-servers',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const userSettings = await settingsStore.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n const hasAllUrls = staticServers.every(s => lcsUrlCache.has(s.name));\n if (!hasAllUrls) {\n await refreshLcsUrlCache();\n }\n\n const servers: McpServerResponse[] = staticServers.map(server => {\n const setting = settingsMap.get(server.name);\n return {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: setting ? Boolean(setting.enabled) : true,\n status: setting?.status ?? 'unknown',\n toolCount: setting?.tool_count ?? 0,\n // DCR servers always have a token (minted per-request); static servers check DB + config.\n hasToken:\n server.auth === 'dcr' || !!(setting?.token || server.token),\n hasUserToken: !!setting?.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n };\n });\n\n res.json({ servers });\n } catch (error) {\n logger.error(`Error listing MCP servers: ${error}`);\n res.status(500).json({ error: 'Failed to list MCP servers' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { url, token } = req.body;\n if (!url || !token) {\n res.status(400).json({ error: 'url and token are required' });\n return;\n }\n\n // SSRF protection: only allow URLs registered in LCS\n let knownUrls = new Set(lcsUrlCache.values());\n if (!knownUrls.has(url)) {\n await refreshLcsUrlCache();\n knownUrls = new Set(lcsUrlCache.values());\n }\n if (!knownUrls.has(url)) {\n res.status(400).json({\n error:\n 'URL not recognized — only MCP server URLs registered in LCS are allowed',\n });\n return;\n }\n\n const result = await mcpValidator.validate(url, token);\n res.json(result);\n } catch (error) {\n logger.error(`Error validating MCP credentials: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/:name/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef, credentials } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n // Resolve URL: LCS cache → fresh LCS fetch\n let serverUrl = resolveServerUrl(server.name);\n if (!serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (!serverUrl) {\n res\n .status(400)\n .json({ error: 'Server has no URL — not found in LCS or config' });\n return;\n }\n\n let effectiveToken: string | undefined;\n if (server.auth === 'dcr') {\n try {\n const { token: dcrToken } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'mcp-actions',\n });\n effectiveToken = dcrToken;\n } catch (err) {\n logger.error(\n `Failed to mint DCR token for server '${name}': ${err}`,\n );\n res.status(502).json({\n error: `Failed to mint authentication token for DCR server '${name}' — check Backstage auth configuration`,\n });\n return;\n }\n } else {\n const setting = await settingsStore.get(name, userEntityRef);\n effectiveToken = setting?.token || server.token;\n }\n if (!effectiveToken) {\n res\n .status(400)\n .json({ error: 'No token available — provide one first' });\n return;\n }\n\n const validation = await mcpValidator.validate(\n serverUrl,\n effectiveToken,\n );\n const status: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n status,\n validation.toolCount,\n );\n\n res.json({\n name,\n status,\n toolCount: validation.toolCount,\n validation,\n });\n } catch (error) {\n logger.error(`Error validating MCP server: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.patch(\n '/mcp-servers/:name',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n\n const body = (req.body ?? {}) as {\n enabled?: boolean;\n token?: string | null;\n };\n const hasEnabledField = Object.prototype.hasOwnProperty.call(\n body,\n 'enabled',\n );\n const hasTokenField = Object.prototype.hasOwnProperty.call(\n body,\n 'token',\n );\n const { enabled, token } = body;\n if (!hasEnabledField && !hasTokenField) {\n res.status(400).json({\n error: 'At least one of enabled or token must be provided',\n });\n return;\n }\n\n const setting = await settingsStore.upsert(name, userEntityRef, {\n enabled: hasEnabledField ? enabled : undefined,\n token: hasTokenField ? token : undefined,\n });\n\n let validation: McpValidationResult | undefined;\n let serverUrl = resolveServerUrl(server.name);\n if (token && !serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (token && serverUrl) {\n validation = await mcpValidator.validate(serverUrl, token);\n const newStatus: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n newStatus,\n validation.toolCount,\n );\n setting.status = newStatus;\n setting.tool_count = validation.toolCount;\n }\n\n const result: Record<string, unknown> = {\n server: {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: Boolean(setting.enabled),\n status: setting.status,\n toolCount: setting.tool_count,\n hasToken:\n server.auth === 'dcr' || !!(setting.token || server.token),\n hasUserToken: !!setting.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n },\n };\n if (validation) result.validation = validation;\n res.json(result);\n } catch (error) {\n logger.error(`Error updating MCP server settings: ${error}`);\n res.status(500).json({ error: 'Failed to update MCP server settings' });\n }\n },\n );\n\n // Returns conversation IDs associated with notebook sessions for filtering\n router.get(\n '/notebook-conversation-ids',\n generalRateLimiter,\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const vectorStoresPage = await vectorStoresOperator.vectorStores.list();\n const vectorStores = vectorStoresPage.data || [];\n\n const conversationIds: string[] = [];\n\n for (const store of vectorStores) {\n const sessionUserId = store.metadata?.user_id as string;\n const conversationId = store.metadata?.conversation_id as\n | string\n | null;\n\n // Only include this user's sessions with a conversation_id\n if (sessionUserId === userEntityRef && conversationId) {\n conversationIds.push(conversationId);\n }\n }\n\n res.json({\n conversation_ids: conversationIds,\n });\n } catch (error) {\n const errormsg = `Error fetching notebook conversation IDs: ${error}`;\n logger.error(errormsg);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: errormsg });\n }\n }\n },\n );\n\n // ─── Proxy Routes ───────────────────────────────────────────────────\n\n router.get(\n '/v1/models',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v1/shields',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.delete(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatDeletePermission),\n apiProxy,\n );\n router.get(\n '/v1/feedback/status',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n\n router.post(\n '/v1/feedback',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(`/v1/feedback receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/feedback?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'sending feedback',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while sending feedback: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query/interrupt',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query/interrupt?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'interrupting query',\n response,\n );\n return;\n }\n response.status(fetchResponse.status).json(await fetchResponse.json());\n } catch (error) {\n const errormsg = `Error while interrupting query: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query',\n express.json({ limit: EXPRESS_JSON_BODY_LIMIT }),\n expensiveRateLimiter,\n validateCompletionsRequest,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n const { provider }: Pick<QueryRequestBody, 'provider'> = request.body;\n try {\n const { userEntityRef, credentials } = getIdentity(request);\n\n logger.info(`/v1/query receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n request.body.media_type = 'application/json'; // set media_type to receive start and end event\n // if system_prompt is defined in lightspeed config\n // set system_prompt to override the default rhdh system prompt\n if (system_prompt && system_prompt.trim().length > 0) {\n request.body.system_prompt = system_prompt;\n }\n\n const requestBody = JSON.stringify(request.body);\n\n // Build MCP headers from config servers + this user's preferences.\n // For servers with auth: dcr, a per-user Backstage token is minted.\n const mcpHeadersValue = await buildMcpHeaders(\n staticServers,\n settingsStore,\n userEntityRef,\n { dcrAuth: { authService: auth, credentials }, logger },\n );\n\n const abortController = new AbortController();\n\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'MCP-HEADERS': mcpHeadersValue,\n },\n body: requestBody,\n signal: abortController.signal,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'processing query',\n response,\n );\n return;\n }\n\n // Pipe the response back to the original response\n if (fetchResponse.body) {\n const nodeStream = Readable.fromWeb(fetchResponse.body as any);\n\n nodeStream.on('error', (error: Error) => {\n logger.error(\n `Upstream stream error while processing query: ${error}`,\n );\n if (response.headersSent) {\n response.destroy();\n } else {\n response.status(500).json({ error: 'Stream error occurred' });\n }\n abortController.abort();\n });\n\n response.on('close', () => {\n if (!response.writableFinished) {\n logger.warn('Client disconnected while processing query');\n nodeStream.destroy();\n abortController.abort();\n }\n });\n\n nodeStream.pipe(response);\n }\n } catch (error) {\n const errormsg = `Error fetching completions from ${provider}: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.put(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const conversation_id = request.params.conversation_id;\n\n const requestBody = JSON.stringify(request.body);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v2/conversations/${conversation_id}?${userQueryParam}`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'updating conversation',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while updating topic summary: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.use((_request, response) => {\n response.status(404).json({ error: 'Requested path is not available' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","DEFAULT_LIGHTSPEED_SERVICE_PORT","DEFAULT_LIGHTSPEED_SERVICE_HOST","createProxyMiddleware","rewriteProxyPath","VectorStoresOperator","createTokenEncryptor","McpUserSettingsStore","McpServerValidator","createPermissionIntegrationRouter","lightspeedPermissions","createIdentityMiddleware","userPermissionAuthorization","createPermissionMiddleware","createRateLimitMiddleware","lightspeedMcpReadPermission","getIdentity","lightspeedMcpManagePermission","NotAllowedError","lightspeedChatReadPermission","lightspeedChatDeletePermission","lightspeedChatCreatePermission","handleLCSFetchError","EXPRESS_JSON_BODY_LIMIT","validateCompletionsRequest","Readable","MiddlewareFactory"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "main": "./dist/index.cjs.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -58,7 +58,7 @@
58
58
  "@backstage/plugin-permission-node": "^0.11.1",
59
59
  "@langchain/core": "^0.3.80",
60
60
  "@langchain/openai": "^0.6.0",
61
- "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^3.0.2",
61
+ "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^3.1.0",
62
62
  "express": "^4.21.1",
63
63
  "express-rate-limit": "^8.2.2",
64
64
  "form-data": "^4.0.6",