diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 5c19b0d234..4328b33204 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -32,6 +32,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{ runner.os }}-build-cache-${{ hashFiles('package.json', 'pnpm-lock.yaml', '**/src/') }}
@@ -64,7 +65,7 @@ jobs:
- name: Build
if: ${{ steps.build-cache.outputs.cache-hit != 'true' }}
- run: pnpm build
+ run: pnpm build:packages
- uses: actions/cache/save@v4
name: Save build cache
@@ -73,6 +74,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{ steps.build-cache.outputs.cache-primary-key }}
@@ -111,6 +113,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{needs.build.outputs.cache-primary-key}}
@@ -150,6 +153,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{needs.build.outputs.cache-primary-key}}
@@ -201,6 +205,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{needs.build.outputs.cache-primary-key}}
@@ -246,6 +251,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{needs.build.outputs.cache-primary-key}}
diff --git a/.github/workflows/react17.yml b/.github/workflows/react17.yml
index 945f961179..2797b3e063 100644
--- a/.github/workflows/react17.yml
+++ b/.github/workflows/react17.yml
@@ -32,6 +32,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{ runner.os }}-REACT17-build-cache-${{ hashFiles('package.json', 'pnpm-lock.yaml', '**/src/') }}
@@ -51,7 +52,7 @@ jobs:
run: pnpm install --prefer-offline # Intentionally not using --frozen-lockfile to allow for pnpm-lock.yaml updates
- name: Build packages
- run: pnpm build
+ run: pnpm build --filter=!'@lg-apps/*'
- uses: actions/cache/save@v4
name: Save build cache
@@ -60,6 +61,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{ steps.build-cache.outputs.cache-primary-key }}
@@ -85,6 +87,7 @@ jobs:
path: |
charts/*/dist/*
chat/*/dist/*
+ mcp-ui/*/dist/*
packages/*/dist/*
tools/*/dist/*
key: ${{needs.build.outputs.cache-primary-key}}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2b3ec4ef95..a14e5a42f6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -35,6 +35,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
@@ -58,7 +59,7 @@ jobs:
- name: Build
if: ${{ steps.build-cache.outputs.cache-hit != 'true' }}
- run: pnpm build
+ run: pnpm build:packages
- name: Generate docs
if: ${{ steps.build-cache.outputs.cache-hit != 'true' }}
@@ -75,6 +76,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
@@ -118,6 +120,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
@@ -171,6 +174,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
@@ -232,6 +236,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
@@ -284,6 +289,7 @@ jobs:
chat/*/dist/*
chat/*/tsdoc.json
chat/*/stories.js
+ mcp-ui/*/dist/*
packages/*/dist/*
packages/*/tsdoc.json
packages/*/stories.js
diff --git a/apps/mcp-ui-app/.gitignore b/apps/mcp-ui-app/.gitignore
new file mode 100644
index 0000000000..c1cf3d2709
--- /dev/null
+++ b/apps/mcp-ui-app/.gitignore
@@ -0,0 +1,37 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+.env.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
diff --git a/apps/mcp-ui-app/README.md b/apps/mcp-ui-app/README.md
new file mode 100644
index 0000000000..dc6a87250a
--- /dev/null
+++ b/apps/mcp-ui-app/README.md
@@ -0,0 +1,73 @@
+# MCP UI App
+
+A Next.js application for the MCP UI, configured for iframe embedding with CORS and CSP headers.
+
+## Getting Started
+
+### 1. Environment Setup
+
+Create a `.env.local` file in the app root with the following variables:
+
+```bash
+# Base URL for the application
+NEXT_PUBLIC_BASE_URL=http://localhost:3000
+
+# Allowed parent origins for iframe embedding (comma-separated)
+ALLOWED_IFRAME_ORIGINS=http://localhost:3000,http://localhost:3001,https://your-app.com
+```
+
+Configuration options:
+
+- `NEXT_PUBLIC_BASE_URL`: The base URL of your application
+- `ALLOWED_IFRAME_ORIGINS`: Comma-separated list of allowed parent origins for iframe embedding
+
+### 2. Install dependencies
+
+```bash
+pnpm install
+```
+
+### 3. Run the development server
+
+```bash
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+## Configuration
+
+### Base URL
+
+The base URL is configured via the `NEXT_PUBLIC_BASE_URL` environment variable and can be accessed in your code:
+
+```typescript
+import config from '@/config';
+
+console.log(config.baseUrl); // http://localhost:3000
+```
+
+### CORS and Iframe Embedding
+
+The app is configured with:
+
+- **CORS headers**: Allow cross-origin requests from specified origins
+- **CSP headers**: Content Security Policy appropriate for iframe embedding
+- **Frame ancestors**: Controls which domains can embed this app in an iframe
+
+To allow your app to be embedded in an iframe from specific domains, add them to the `ALLOWED_IFRAME_ORIGINS` environment variable.
+
+## Build
+
+This app is excluded from the default `pnpm build` command in the workspace. To build this app specifically, run:
+
+```bash
+cd apps/mcp-ui-app
+pnpm build
+```
+
+Or from the workspace root:
+
+```bash
+pnpm build:apps
+```
diff --git a/apps/mcp-ui-app/next.config.js b/apps/mcp-ui-app/next.config.js
new file mode 100644
index 0000000000..6c1d08e0c8
--- /dev/null
+++ b/apps/mcp-ui-app/next.config.js
@@ -0,0 +1,60 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ transpilePackages: [
+ '@lg-mcp-ui/list-databases',
+ '@leafygreen-ui/card',
+ '@leafygreen-ui/typography',
+ '@leafygreen-ui/emotion',
+ '@leafygreen-ui/tokens',
+ '@leafygreen-ui/lib',
+ ],
+
+ async headers() {
+ // Get allowed origins from environment variable
+ const allowedOrigins = process.env.ALLOWED_IFRAME_ORIGINS?.split(',') || [
+ '*',
+ ];
+
+ return [
+ {
+ // Apply to all routes
+ source: '/:path*',
+ headers: [
+ // CORS headers for iframe embedding
+ {
+ key: 'Access-Control-Allow-Origin',
+ value: allowedOrigins[0] || '*', // Use first origin or wildcard
+ },
+ {
+ key: 'Access-Control-Allow-Methods',
+ value: 'GET, POST, PUT, DELETE, OPTIONS',
+ },
+ {
+ key: 'Access-Control-Allow-Headers',
+ value: 'Content-Type, Authorization',
+ },
+ {
+ key: 'Access-Control-Allow-Credentials',
+ value: 'true',
+ },
+ // Content Security Policy for iframe embedding
+ {
+ key: 'Content-Security-Policy',
+ value: [
+ "default-src 'self'",
+ "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self' data:",
+ "connect-src 'self'",
+ `frame-ancestors ${allowedOrigins.join(' ')}`, // Allows embedding in iframes from these origins
+ ].join('; '),
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
diff --git a/apps/mcp-ui-app/package.json b/apps/mcp-ui-app/package.json
new file mode 100644
index 0000000000..7f52989096
--- /dev/null
+++ b/apps/mcp-ui-app/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@lg-apps/mcp-ui-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@lg-mcp-ui/list-databases": "workspace:*",
+ "next": "^14.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.12.5",
+ "@types/react": "18.2.23",
+ "@types/react-dom": "18.2.8",
+ "typescript": "~5.8.0"
+ }
+}
+
diff --git a/apps/mcp-ui-app/src/app/layout.tsx b/apps/mcp-ui-app/src/app/layout.tsx
new file mode 100644
index 0000000000..9ae2c7da9c
--- /dev/null
+++ b/apps/mcp-ui-app/src/app/layout.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import type { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'MCP UI App',
+ description: 'MCP UI Application',
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
{children}
+
+ );
+}
diff --git a/apps/mcp-ui-app/src/app/list-databases/page.tsx b/apps/mcp-ui-app/src/app/list-databases/page.tsx
new file mode 100644
index 0000000000..43e4e0dfb5
--- /dev/null
+++ b/apps/mcp-ui-app/src/app/list-databases/page.tsx
@@ -0,0 +1,8 @@
+'use client';
+
+import React from 'react';
+import { ListDatabases } from '@lg-mcp-ui/list-databases';
+
+export default function ListDatabasesPage() {
+ return ;
+}
diff --git a/apps/mcp-ui-app/src/app/page.tsx b/apps/mcp-ui-app/src/app/page.tsx
new file mode 100644
index 0000000000..aca119d09b
--- /dev/null
+++ b/apps/mcp-ui-app/src/app/page.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+
+import config from '@/config';
+
+export default function Home() {
+ return (
+
+ MCP UI App
+ Welcome to the MCP UI Application!
+
+
+ Configuration
+
+
+ Base URL: {config.baseUrl}
+
+
+ Allowed Origins:{' '}
+ {config.allowedIframeOrigins.join(', ') || 'Not configured'}
+
+
+
+ );
+}
diff --git a/apps/mcp-ui-app/src/config/index.ts b/apps/mcp-ui-app/src/config/index.ts
new file mode 100644
index 0000000000..85009db6c0
--- /dev/null
+++ b/apps/mcp-ui-app/src/config/index.ts
@@ -0,0 +1,18 @@
+/**
+ * Application configuration
+ */
+
+export const config = {
+ /**
+ * Base URL of the application
+ * Defaults to localhost:3000 in development
+ */
+ baseUrl: process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000',
+
+ /**
+ * Allowed origins for iframe embedding
+ */
+ allowedIframeOrigins: process.env.ALLOWED_IFRAME_ORIGINS?.split(',') || [],
+} as const;
+
+export default config;
diff --git a/apps/mcp-ui-app/tsconfig.json b/apps/mcp-ui-app/tsconfig.json
new file mode 100644
index 0000000000..7f64e8882a
--- /dev/null
+++ b/apps/mcp-ui-app/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
+
diff --git a/mcp-ui/list-databases/package.json b/mcp-ui/list-databases/package.json
new file mode 100644
index 0000000000..8140ece94c
--- /dev/null
+++ b/mcp-ui/list-databases/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@lg-mcp-ui/list-databases",
+ "version": "0.1.0",
+ "private": true,
+ "main": "./dist/umd/index.js",
+ "module": "./dist/esm/index.js",
+ "types": "./dist/types/index.d.ts",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "lg-build bundle",
+ "tsc": "lg-build tsc",
+ "docs": "lg-build docs",
+ "dev": "lg-build bundle --watch"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ },
+ "dependencies": {
+ "@leafygreen-ui/tokens": "workspace:^",
+ "@leafygreen-ui/lib": "workspace:^",
+ "@leafygreen-ui/palette": "workspace:^"
+ },
+ "devDependencies": {
+ "@lg-tools/build": "workspace:^"
+ },
+ "exports": {
+ ".": {
+ "development": "./src/index.ts",
+ "types": "./dist/types/index.d.ts",
+ "import": "./dist/esm/index.js",
+ "require": "./dist/umd/index.js"
+ }
+ }
+}
diff --git a/mcp-ui/list-databases/src/ListDatabases.tsx b/mcp-ui/list-databases/src/ListDatabases.tsx
new file mode 100644
index 0000000000..7161bb3e44
--- /dev/null
+++ b/mcp-ui/list-databases/src/ListDatabases.tsx
@@ -0,0 +1,88 @@
+// 'use client';
+
+import React from 'react';
+
+import { palette } from '@leafygreen-ui/palette';
+import {
+ borderRadius,
+ fontFamilies,
+ fontWeights,
+ spacing,
+ typeScales,
+} from '@leafygreen-ui/tokens';
+
+import { ListDatabasesProps } from './ListDatabases.types';
+
+const H3 = ({ children }: { children: React.ReactNode }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+const Body = ({ children }: { children: React.ReactNode }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+const Card = ({ children }: { children: React.ReactNode }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default function ListDatabases({ databases }: ListDatabasesProps) {
+ if (databases.length === 0) {
+ return (
+
+ No databases found
+
+ );
+ }
+
+ return (
+
+ Databases
+
+ {databases.map(database => (
+ -
+ {database}
+
+ ))}
+
+
+ );
+}
diff --git a/mcp-ui/list-databases/src/ListDatabases.types.ts b/mcp-ui/list-databases/src/ListDatabases.types.ts
new file mode 100644
index 0000000000..b492356476
--- /dev/null
+++ b/mcp-ui/list-databases/src/ListDatabases.types.ts
@@ -0,0 +1,3 @@
+export interface ListDatabasesProps {
+ databases: Array;
+}
diff --git a/mcp-ui/list-databases/src/index.ts b/mcp-ui/list-databases/src/index.ts
new file mode 100644
index 0000000000..75629fbd30
--- /dev/null
+++ b/mcp-ui/list-databases/src/index.ts
@@ -0,0 +1,2 @@
+export { default as ListDatabases } from './ListDatabases';
+export type { ListDatabasesProps } from './ListDatabases.types';
diff --git a/mcp-ui/list-databases/tsconfig.json b/mcp-ui/list-databases/tsconfig.json
new file mode 100644
index 0000000000..ba0251cda9
--- /dev/null
+++ b/mcp-ui/list-databases/tsconfig.json
@@ -0,0 +1,31 @@
+{
+ "extends": "@lg-tools/build/config/package.tsconfig.json",
+ "compilerOptions": {
+ "paths": {
+ "@leafygreen-ui/*": [
+ "../../packages/*/src"
+ ]
+ }
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "**/*.stories.*"
+ ],
+ "references": [
+ {
+ "path": "../../packages/card"
+ },
+ {
+ "path": "../../packages/typography"
+ },
+ {
+ "path": "../../packages/emotion"
+ },
+ {
+ "path": "../../packages/lib"
+ }
+ ]
+}
+
diff --git a/package.json b/package.json
index fbcba81d8d..196927163b 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,10 @@
"init:react17": "pnpm clean; npx node ./scripts/react17/init.mjs; pnpm run init",
"create-package": "lg create",
"build": "turbo run build tsc",
+ "build:apps": "turbo run build --filter='@lg-apps/*'",
"build:cli": "turbo run build tsc --filter=@lg-tools/cli",
+ "build:packages": "turbo run build tsc --filter=!'@lg-apps/*'",
+ "dev:mcp-ui": "turbo run dev --filter=@lg-apps/mcp-ui-app",
"build:docs": "turbo run docs",
"build:tsc": "turbo run tsc",
"build:ts-downlevel": "pnpm recursive exec lg-ts-downlevel",
@@ -95,7 +98,8 @@
"@leafygreen-ui": "packages",
"@lg-charts": "charts",
"@lg-chat": "chat",
- "@lg-tools": "tools"
+ "@lg-tools": "tools",
+ "@lg-mcp-ui": "mcp-ui"
}
},
"keywords": [
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7b285cbc95..a4a086db5a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -121,6 +121,34 @@ importers:
specifier: ~5.8.0
version: 5.8.3
+ apps/mcp-ui-app:
+ dependencies:
+ '@lg-mcp-ui/list-databases':
+ specifier: workspace:*
+ version: link:../../mcp-ui/list-databases
+ next:
+ specifier: ^14.2.0
+ version: 14.2.33(@babel/core@7.24.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.12.5
+ version: 20.19.9
+ '@types/react':
+ specifier: 18.2.23
+ version: 18.2.23
+ '@types/react-dom':
+ specifier: 18.2.8
+ version: 18.2.8
+ typescript:
+ specifier: ~5.8.0
+ version: 5.8.3
+
charts/chart-card:
dependencies:
'@dnd-kit/sortable':
@@ -952,6 +980,25 @@ importers:
specifier: workspace:^
version: link:../../tools/build
+ mcp-ui/list-databases:
+ dependencies:
+ '@leafygreen-ui/lib':
+ specifier: workspace:^
+ version: link:../../packages/lib
+ '@leafygreen-ui/palette':
+ specifier: workspace:^
+ version: link:../../packages/palette
+ '@leafygreen-ui/tokens':
+ specifier: workspace:^
+ version: link:../../packages/tokens
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ devDependencies:
+ '@lg-tools/build':
+ specifier: workspace:^
+ version: link:../../tools/build
+
packages/a11y:
dependencies:
'@leafygreen-ui/emotion':
@@ -6005,6 +6052,63 @@ packages:
'@types/react': '>=16'
react: '>=16'
+ '@next/env@14.2.33':
+ resolution: {integrity: sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==}
+
+ '@next/swc-darwin-arm64@14.2.33':
+ resolution: {integrity: sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@next/swc-darwin-x64@14.2.33':
+ resolution: {integrity: sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@next/swc-linux-arm64-gnu@14.2.33':
+ resolution: {integrity: sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@next/swc-linux-arm64-musl@14.2.33':
+ resolution: {integrity: sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@next/swc-linux-x64-gnu@14.2.33':
+ resolution: {integrity: sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@next/swc-linux-x64-musl@14.2.33':
+ resolution: {integrity: sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@next/swc-win32-arm64-msvc@14.2.33':
+ resolution: {integrity: sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@next/swc-win32-ia32-msvc@14.2.33':
+ resolution: {integrity: sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==}
+ engines: {node: '>= 10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@next/swc-win32-x64-msvc@14.2.33':
+ resolution: {integrity: sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
@@ -6672,6 +6776,12 @@ packages:
resolution: {integrity: sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==}
engines: {node: '>=14'}
+ '@swc/counter@0.1.3':
+ resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+
+ '@swc/helpers@0.5.5':
+ resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
+
'@tanstack/react-table@8.21.3':
resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==}
engines: {node: '>=12'}
@@ -7518,6 +7628,10 @@ packages:
builtin-status-codes@3.0.0:
resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==}
+ busboy@1.6.0:
+ resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
+ engines: {node: '>=10.16.0'}
+
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
@@ -7631,6 +7745,9 @@ packages:
resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
engines: {node: '>= 10.0'}
+ client-only@0.0.1:
+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+
clipboard@2.0.11:
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
@@ -9881,6 +9998,24 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+ next@14.2.33:
+ resolution: {integrity: sha512-GiKHLsD00t4ACm1p00VgrI0rUFAC9cRDGReKyERlM57aeEZkOQGcZTpIbsGn0b562FTPJWmYfKwplfO9EaT6ng==}
+ engines: {node: '>=18.17.0'}
+ hasBin: true
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+ '@playwright/test': ^1.41.2
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ sass: ^1.3.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@playwright/test':
+ optional: true
+ sass:
+ optional: true
+
nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
@@ -10272,6 +10407,10 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ postcss@8.4.31:
+ resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
+ engines: {node: ^10 || ^12 || >=14}
+
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -10904,6 +11043,10 @@ packages:
stream@0.0.3:
resolution: {integrity: sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==}
+ streamsearch@1.1.0:
+ resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
+ engines: {node: '>=10.0.0'}
+
string-length@4.0.2:
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
engines: {node: '>=10'}
@@ -11001,6 +11144,19 @@ packages:
style-to-object@0.4.4:
resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==}
+ styled-jsx@5.1.1:
+ resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ '@babel/core': '*'
+ babel-plugin-macros: '*'
+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ babel-plugin-macros:
+ optional: true
+
stylis@4.2.0:
resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
@@ -14278,6 +14434,35 @@ snapshots:
'@types/react': 18.2.23
react: 18.3.1
+ '@next/env@14.2.33': {}
+
+ '@next/swc-darwin-arm64@14.2.33':
+ optional: true
+
+ '@next/swc-darwin-x64@14.2.33':
+ optional: true
+
+ '@next/swc-linux-arm64-gnu@14.2.33':
+ optional: true
+
+ '@next/swc-linux-arm64-musl@14.2.33':
+ optional: true
+
+ '@next/swc-linux-x64-gnu@14.2.33':
+ optional: true
+
+ '@next/swc-linux-x64-musl@14.2.33':
+ optional: true
+
+ '@next/swc-win32-arm64-msvc@14.2.33':
+ optional: true
+
+ '@next/swc-win32-ia32-msvc@14.2.33':
+ optional: true
+
+ '@next/swc-win32-x64-msvc@14.2.33':
+ optional: true
+
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
dependencies:
eslint-scope: 5.1.1
@@ -15052,6 +15237,13 @@ snapshots:
- supports-color
- typescript
+ '@swc/counter@0.1.3': {}
+
+ '@swc/helpers@0.5.5':
+ dependencies:
+ '@swc/counter': 0.1.3
+ tslib: 2.8.1
+
'@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/table-core': 8.21.3
@@ -16121,6 +16313,10 @@ snapshots:
builtin-status-codes@3.0.0: {}
+ busboy@1.6.0:
+ dependencies:
+ streamsearch: 1.1.0
+
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
@@ -16228,6 +16424,8 @@ snapshots:
dependencies:
source-map: 0.6.1
+ client-only@0.0.1: {}
+
clipboard@2.0.11:
dependencies:
good-listener: 1.2.2
@@ -19235,6 +19433,32 @@ snapshots:
neo-async@2.6.2: {}
+ next@14.2.33(@babel/core@7.24.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2):
+ dependencies:
+ '@next/env': 14.2.33
+ '@swc/helpers': 0.5.5
+ busboy: 1.6.0
+ caniuse-lite: 1.0.30001727
+ graceful-fs: 4.2.11
+ postcss: 8.4.31
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ styled-jsx: 5.1.1(@babel/core@7.24.3)(react@18.3.1)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 14.2.33
+ '@next/swc-darwin-x64': 14.2.33
+ '@next/swc-linux-arm64-gnu': 14.2.33
+ '@next/swc-linux-arm64-musl': 14.2.33
+ '@next/swc-linux-x64-gnu': 14.2.33
+ '@next/swc-linux-x64-musl': 14.2.33
+ '@next/swc-win32-arm64-msvc': 14.2.33
+ '@next/swc-win32-ia32-msvc': 14.2.33
+ '@next/swc-win32-x64-msvc': 14.2.33
+ sass: 1.89.2
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+
nice-try@1.0.5: {}
no-case@3.0.4:
@@ -19667,6 +19891,12 @@ snapshots:
postcss-value-parser@4.2.0: {}
+ postcss@8.4.31:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
postcss@8.5.6:
dependencies:
nanoid: 3.3.11
@@ -20429,6 +20659,8 @@ snapshots:
dependencies:
component-emitter: 2.0.0
+ streamsearch@1.1.0: {}
+
string-length@4.0.2:
dependencies:
char-regex: 1.0.2
@@ -20546,6 +20778,13 @@ snapshots:
dependencies:
inline-style-parser: 0.1.1
+ styled-jsx@5.1.1(@babel/core@7.24.3)(react@18.3.1):
+ dependencies:
+ client-only: 0.0.1
+ react: 18.3.1
+ optionalDependencies:
+ '@babel/core': 7.24.3
+
stylis@4.2.0: {}
superstruct@2.0.2: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index e01ae25f2c..89652f8019 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,6 +1,8 @@
packages:
- # all packages in direct subdirectories of charts/, chat/, packages/, & tools/
+ # all packages in direct subdirectories of apps/, charts/, chat/, packages/, & tools/
+ - 'apps/*'
- 'charts/*'
- 'chat/*'
+ - 'mcp-ui/*'
- 'packages/*'
- 'tools/*'
diff --git a/scripts/react17/Dockerfile b/scripts/react17/Dockerfile
index 89d0bcf4c0..16e58eb675 100644
--- a/scripts/react17/Dockerfile
+++ b/scripts/react17/Dockerfile
@@ -2,7 +2,7 @@ FROM node:18.20.8
# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive
-ENV PNPM_VERSION=9.15.0
+ENV PNPM_VERSION=10.18.3
# Install system dependencies
RUN apt-get update && apt-get install -y \
diff --git a/scripts/react17/init.mjs b/scripts/react17/init.mjs
index 6824cd0a2b..fcab07f8c4 100644
--- a/scripts/react17/init.mjs
+++ b/scripts/react17/init.mjs
@@ -65,7 +65,13 @@ async function main() {
function findTsConfigFiles(dir) {
/** @type {Array} */
const results = [];
- const packageDirs = ['packages', 'charts', 'chat', 'tools'];
+
+ // Read the root package.json to get package directories dynamically
+ const rootPackage = JSON.parse(
+ fs.readFileSync(ROOT_PACKAGE_JSON_PATH, 'utf-8'),
+ );
+ // Get package directories from lg.scopes
+ const packageDirs = Object.values(rootPackage.lg?.scopes ?? {});
for (const packageDir of packageDirs) {
const packagePath = path.join(dir, packageDir);
diff --git a/scripts/react17/test-react17.sh b/scripts/react17/test-react17.sh
index a4a6e7d607..10c11902ef 100755
--- a/scripts/react17/test-react17.sh
+++ b/scripts/react17/test-react17.sh
@@ -100,7 +100,8 @@ docker run --name "${CONTAINER_NAME}" \
/bin/bash -c '
set -e
npx node ./scripts/react17/init.mjs
- pnpm run init
+ pnpm install
+ pnpm run build:packages
pnpm run test --react17 -- --testTimeout=120000
pnpm build-storybook
'
diff --git a/tools/install/src/ALL_PACKAGES.ts b/tools/install/src/ALL_PACKAGES.ts
index 238a0402e6..3f608707d0 100644
--- a/tools/install/src/ALL_PACKAGES.ts
+++ b/tools/install/src/ALL_PACKAGES.ts
@@ -117,4 +117,5 @@ export const ALL_PACKAGES = [
'@lg-tools/test-harnesses',
'@lg-tools/update',
'@lg-tools/validate',
+ '@lg-mcp-ui/list-databases',
] as const;
diff --git a/tools/test/config/react17/jest.config.js b/tools/test/config/react17/jest.config.js
index 37f84bcf85..10407c379b 100644
--- a/tools/test/config/react17/jest.config.js
+++ b/tools/test/config/react17/jest.config.js
@@ -42,7 +42,12 @@ module.exports = {
testEnvironment: 'jsdom',
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
- testPathIgnorePatterns: ['/node_modules/', '/deprecated-packages/'],
+ testPathIgnorePatterns: [
+ '/node_modules/',
+ '/deprecated-packages/',
+ '/apps/',
+ '/mcp-ui/',
+ ],
// The regexp pattern Jest uses to detect test files
testRegex: '.spec.[jt]sx?$',
diff --git a/turbo.json b/turbo.json
index 1494e6f221..1df11b6653 100644
--- a/turbo.json
+++ b/turbo.json
@@ -7,7 +7,13 @@
"build": {
"dependsOn": ["^build", "^prebuild", "prebuild"],
"inputs": ["$TURBO_DEFAULT$", "!**/*.stories.{tsx,jsx,mdx}"],
- "outputs": ["dist/**/*.js", "dist/**/*.js.map", "stories.js"]
+ "outputs": [
+ "dist/**/*.js",
+ "dist/**/*.js.map",
+ "stories.js",
+ ".next/**",
+ "out/**"
+ ]
},
"tsc": {
"dependsOn": ["^tsc", "^prebuild", "prebuild"],
@@ -20,6 +26,10 @@
"docs": {
"dependsOn": ["^tsc"],
"outputs": ["tsdoc.json"]
+ },
+ "dev": {
+ "cache": false,
+ "persistent": true
}
}
}