diff --git a/packages/dev/mcp/react-aria/README.md b/packages/dev/mcp/react-aria/README.md index 491dfa9f50c..3a3f0e4476b 100644 --- a/packages/dev/mcp/react-aria/README.md +++ b/packages/dev/mcp/react-aria/README.md @@ -109,6 +109,10 @@ Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/m | `get_react_aria_page_info` | `{ page_name: string }` | Return page description and list of section titles. | | `get_react_aria_page` | `{ page_name: string, section_name?: string }` | Return full page markdown, or only the specified section. | +## Privacy Policy + +See [Adobe's privacy policy](https://www.adobe.com/privacy/policy.html). + ## Development ### Testing locally @@ -135,4 +139,12 @@ Update your MCP client configuration to use the local MCP server: } } } +``` + +## Bundling + +To build an [MCP Bundle (MCPB)](https://github.com/modelcontextprotocol/mcpb), run: + +```bash +yarn workspace @react-spectrum/s2-docs generate:mcpb ``` \ No newline at end of file diff --git a/packages/dev/mcp/react-aria/src/index.ts b/packages/dev/mcp/react-aria/src/index.ts index 5853319e33c..191463f0a1a 100644 --- a/packages/dev/mcp/react-aria/src/index.ts +++ b/packages/dev/mcp/react-aria/src/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node /// -import {errorToString} from '../../shared/src/utils.js'; +import {errorToString, readPackageVersion} from '../../shared/src/utils.js'; import {startServer} from '../../shared/src/server.js'; // CLI entry for React Aria @@ -11,7 +11,7 @@ import {startServer} from '../../shared/src/server.js'; console.log('Usage: npx @react-aria/mcp@latest\n\nStarts the MCP server for React Aria documentation.'); process.exit(0); } - await startServer('react-aria', '0.1.0'); + await startServer('react-aria', readPackageVersion(import.meta.url)); } catch (err) { console.error(errorToString(err)); process.exit(1); diff --git a/packages/dev/mcp/s2/README.md b/packages/dev/mcp/s2/README.md index 72d66aa6394..5fc8d69812b 100644 --- a/packages/dev/mcp/s2/README.md +++ b/packages/dev/mcp/s2/README.md @@ -111,6 +111,10 @@ Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/m | `search_s2_icons` | `{ terms: string \| string[] }` | Search S2 workflow icon names. | | `search_s2_illustrations` | `{ terms: string \| string[] }` | Search S2 illustration names. | +## Privacy Policy + +See [Adobe's privacy policy](https://www.adobe.com/privacy/policy.html). + ## Development ### Testing locally @@ -137,4 +141,12 @@ Update your MCP client configuration to use the local MCP server: } } } +``` + +## Bundling + +To build an [MCP Bundle (MCPB)](https://github.com/modelcontextprotocol/mcpb), run: + +```bash +yarn workspace @react-spectrum/s2-docs generate:mcpb ``` \ No newline at end of file diff --git a/packages/dev/mcp/s2/src/index.ts b/packages/dev/mcp/s2/src/index.ts index b8a8418cd76..bac3f62cca3 100644 --- a/packages/dev/mcp/s2/src/index.ts +++ b/packages/dev/mcp/s2/src/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node /// -import {errorToString} from '../../shared/src/utils.js'; +import {errorToString, readPackageVersion} from '../../shared/src/utils.js'; import {listIconNames, listIllustrationNames, loadIconAliases, loadIllustrationAliases, loadStyleMacroPropertyValues} from './s2-data.js'; import type {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js'; import {startServer} from '../../shared/src/server.js'; @@ -15,13 +15,14 @@ import {z} from 'zod'; process.exit(0); } - await startServer('s2', '0.1.0', (server: McpServer) => { + await startServer('s2', readPackageVersion(import.meta.url), (server: McpServer) => { server.registerTool( 'search_s2_icons', { title: 'Search S2 icons', description: 'Searches the S2 workflow icon set by one or more terms; returns matching icon names.', - inputSchema: {terms: z.union([z.string(), z.array(z.string())])} + inputSchema: {terms: z.union([z.string(), z.array(z.string())])}, + annotations: {readOnlyHint: true} }, async ({terms}) => { const allNames = listIconNames(); @@ -57,7 +58,8 @@ import {z} from 'zod'; { title: 'Search S2 illustrations', description: 'Searches the S2 illustrations set by one or more terms; returns matching illustration names.', - inputSchema: {terms: z.union([z.string(), z.array(z.string())])} + inputSchema: {terms: z.union([z.string(), z.array(z.string())])}, + annotations: {readOnlyHint: true} }, async ({terms}) => { const allNames = listIllustrationNames(); @@ -93,7 +95,8 @@ import {z} from 'zod'; { title: 'Get style macro property values', description: 'Returns the allowed values for a given S2 style macro property (including expanded color/spacing value lists where applicable).', - inputSchema: {propertyName: z.string()} + inputSchema: {propertyName: z.string()}, + annotations: {readOnlyHint: true} }, async ({propertyName}) => { const name = String(propertyName ?? '').trim(); diff --git a/packages/dev/mcp/shared/src/server.ts b/packages/dev/mcp/shared/src/server.ts index be545f7d314..ac0a813822c 100644 --- a/packages/dev/mcp/shared/src/server.ts +++ b/packages/dev/mcp/shared/src/server.ts @@ -30,7 +30,8 @@ export async function startServer( { title: library === 's2' ? 'List React Spectrum (@react-spectrum/s2) docs pages' : 'List React Aria docs pages', description: `Returns a list of available pages in the ${library} docs.`, - inputSchema: {includeDescription: z.boolean().optional()} + inputSchema: {includeDescription: z.boolean().optional()}, + annotations: {readOnlyHint: true} }, async ({includeDescription}) => { const pages = await buildPageIndex(library); @@ -48,7 +49,8 @@ export async function startServer( { title: 'Get page info', description: 'Returns page description and list of sections for a given page.', - inputSchema: {page_name: z.string()} + inputSchema: {page_name: z.string()}, + annotations: {readOnlyHint: true} }, async ({page_name}) => { const ref = await resolvePageRef(library, page_name); @@ -67,7 +69,8 @@ export async function startServer( { title: 'Get page markdown', description: 'Returns the full markdown content for a page, or a specific section if provided.', - inputSchema: {page_name: z.string(), section_name: z.string().optional()} + inputSchema: {page_name: z.string(), section_name: z.string().optional()}, + annotations: {readOnlyHint: true} }, async ({page_name, section_name}) => { const ref = await resolvePageRef(library, page_name); diff --git a/packages/dev/mcp/shared/src/utils.ts b/packages/dev/mcp/shared/src/utils.ts index a573f2c3d96..2de6d641357 100644 --- a/packages/dev/mcp/shared/src/utils.ts +++ b/packages/dev/mcp/shared/src/utils.ts @@ -1,3 +1,24 @@ +import {dirname, join} from 'path'; +import {fileURLToPath} from 'url'; +import {readFileSync} from 'fs'; + +// Resolves the version from the nearest package.json above the CLI entry point. +// Both the npm-published layout (dist//src/index.js) and the .mcpb bundle +// layout (server//src/index.js) place package.json three levels up. +export function readPackageVersion(entryUrl: string): string { + const entryDir = dirname(fileURLToPath(entryUrl)); + const pkgPath = join(entryDir, '..', '..', '..', 'package.json'); + try { + const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')); + if (typeof pkg.version === 'string' && pkg.version.length > 0) { + return pkg.version; + } + } catch { + // fall through + } + return '0.0.0'; +} + export function errorToString(err: unknown): string { if (err && typeof err === 'object' && 'stack' in err && typeof (err as any).stack === 'string') { return (err as any).stack as string; diff --git a/packages/dev/s2-docs/package.json b/packages/dev/s2-docs/package.json index eb14a2a3041..b59b8ab3eaa 100644 --- a/packages/dev/s2-docs/package.json +++ b/packages/dev/s2-docs/package.json @@ -10,7 +10,8 @@ "build:s2": "LIBRARY=s2 parcel build 'pages/s2/**/*.mdx' --config .parcelrc-s2-docs --dist-dir dist/s2 --cache-dir ../../../.parcel-cache/s2", "build:react-aria": "LIBRARY=react-aria parcel build 'pages/react-aria/**/*.mdx' --config .parcelrc-s2-docs --dist-dir dist/react-aria --cache-dir ../../../.parcel-cache/react-aria", "generate:og": "node scripts/generateOGImages.mjs", - "generate:md": "node scripts/generateMarkdownDocs.mjs" + "generate:md": "node scripts/generateMarkdownDocs.mjs", + "generate:mcpb": "node scripts/generateMcpb.mjs" }, "targets": { "react-static": { @@ -71,6 +72,7 @@ "vanilla-starter": "../../../starters/docs/src" }, "devDependencies": { + "@anthropic-ai/mcpb": "^2.1.2", "axe-playwright": "^2.2.2", "playwright": "^1.57.0" }, diff --git a/packages/dev/s2-docs/pages/s2/ai.mdx b/packages/dev/s2-docs/pages/s2/ai.mdx index 7a13058bfd7..4755d4dc5c9 100644 --- a/packages/dev/s2-docs/pages/s2/ai.mdx +++ b/packages/dev/s2-docs/pages/s2/ai.mdx @@ -121,4 +121,4 @@ Add the `.md` extension to the URL to get the markdown version of a page. Additi ## llms.txt -The llms.txt file contains a list of all the markdown pages available in the React Spectrum documentation. +The llms.txt file contains a list of all the markdown pages available in the React Spectrum documentation. \ No newline at end of file diff --git a/packages/dev/s2-docs/scripts/generateMcpb.mjs b/packages/dev/s2-docs/scripts/generateMcpb.mjs new file mode 100644 index 00000000000..09096c3bdd9 --- /dev/null +++ b/packages/dev/s2-docs/scripts/generateMcpb.mjs @@ -0,0 +1,268 @@ +import {execFileSync} from 'child_process'; +import {fileURLToPath} from 'url'; +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import sharp from 'sharp'; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(scriptDir, '../../../../'); + +const assetsDir = path.join(scriptDir, '../assets'); + +const sharedPageTools = (libraryLabel, toolPrefix) => [ + { + name: `list_${toolPrefix}_pages`, + description: `Returns a list of available pages in the ${libraryLabel} docs.` + }, + { + name: `get_${toolPrefix}_page_info`, + description: 'Returns page description and list of sections for a given page.' + }, + { + name: `get_${toolPrefix}_page`, + description: 'Returns the full markdown content for a page, or a specific section if provided.' + } +]; + +const libraries = { + s2: { + packageDir: path.join(repoRoot, 'packages/dev/mcp/s2'), + packageName: '@react-spectrum/mcp', + outputDir: path.join(repoRoot, 'packages/dev/s2-docs/dist/s2'), + outputFile: 'react-spectrum-s2.mcpb', + serverEntryPoint: 'server/s2/src/index.js', + displayName: 'React Spectrum (S2)', + extensionName: 'react-spectrum-s2', + description: 'Build apps with Adobe\'s React Spectrum component library.', + longDescription: 'Provides tools for browsing the React Spectrum (S2) documentation, including listing and reading pages, searching for available icons and illustrations, and looking up available styling token values. Uses the React Spectrum documentation content available at https://react-spectrum.adobe.com.', + homepage: 'https://react-spectrum.adobe.com/', + documentation: 'https://react-spectrum.adobe.com/ai.html', + iconSvg: path.join(assetsDir, 'rsp-favicon.svg'), + keywords: ['react', 'react-spectrum', 'spectrum', 'adobe', 'design-system', 'components'], + tools: [ + ...sharedPageTools('React Spectrum (S2)', 's2'), + { + name: 'search_s2_icons', + description: 'Searches the S2 workflow icon set by one or more terms; returns matching icon names.' + }, + { + name: 'search_s2_illustrations', + description: 'Searches the S2 illustrations set by one or more terms; returns matching illustration names.' + }, + { + name: 'get_style_macro_property_values', + description: 'Returns the allowed values for a given S2 style macro property (including expanded color/spacing value lists where applicable).' + } + ], + srcDirs: [ + { + from: path.join(repoRoot, 'packages/dev/mcp/s2/dist/s2/src'), + to: 'server/s2/src' + }, + { + from: path.join(repoRoot, 'packages/dev/mcp/s2/dist/shared/src'), + to: 'server/shared/src' + }, + { + from: path.join(repoRoot, 'packages/dev/mcp/s2/dist/data'), + to: 'server/data' + } + ] + }, + 'react-aria': { + packageDir: path.join(repoRoot, 'packages/dev/mcp/react-aria'), + packageName: '@react-aria/mcp', + outputDir: path.join(repoRoot, 'packages/dev/s2-docs/dist/react-aria'), + outputFile: 'react-aria.mcpb', + serverEntryPoint: 'server/react-aria/src/index.js', + displayName: 'React Aria', + extensionName: 'react-aria', + description: 'Build accessible UI components with React Aria.', + longDescription: 'Provides tools for browsing the React Aria documentation. Uses the React Aria documentation content available at https://react-aria.adobe.com.', + homepage: 'https://react-aria.adobe.com/', + documentation: 'https://react-aria.adobe.com/ai.html', + iconSvg: path.join(assetsDir, 'react-aria-favicon.svg'), + keywords: ['react', 'react-aria', 'adobe', 'accessibility', 'aria', 'design-system', 'components'], + tools: sharedPageTools('React Aria', 'react_aria'), + srcDirs: [ + { + from: path.join(repoRoot, 'packages/dev/mcp/react-aria/dist/react-aria/src'), + to: 'server/react-aria/src' + }, + { + from: path.join(repoRoot, 'packages/dev/mcp/react-aria/dist/shared/src'), + to: 'server/shared/src' + } + ] + } +}; + +const requestedLibraries = process.argv.slice(2); + +/** + * Generate an MCPB bundle for a given library. This makes the MCP servers easier to install in certain MCP clients like Claude Desktop. + * Reference: https://github.com/modelcontextprotocol/mcpb + */ +async function generateBundle(libraryName, config) { + const packageJsonPath = path.join(config.packageDir, 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `rsp-${libraryName}-mcpb-`)); + + try { + for (const dir of config.srcDirs) { + if (!fs.existsSync(dir.from)) { + throw new Error(`Missing built MCP output at ${dir.from}. Build ${config.packageName} first.`); + } + copyDirectory(dir.from, path.join(tempDir, dir.to)); + } + + const bundledPackages = new Set(); + for (const dependency of Object.keys(packageJson.dependencies || {})) { + copyDependencyTree(dependency, path.join(tempDir, 'node_modules'), bundledPackages); + } + + // Convert SVG icon to 512x512 PNG for the bundle. + const iconFile = 'icon.png'; + let svg = fs.readFileSync(config.iconSvg, 'utf8'); + // The React Aria favicon uses light-dark() CSS which sharp doesn't support. + // Replace it with the dark-mode color so the icon works on any background. + svg = svg.replace(/light-dark\([^,]+,\s*([^)]+)\)/, '$1'); + await sharp(Buffer.from(svg)) + .resize(448, 448, {fit: 'contain', background: {r: 0, g: 0, b: 0, alpha: 0}}) + .extend({top: 32, bottom: 32, left: 32, right: 32, background: {r: 0, g: 0, b: 0, alpha: 0}}) + .png().toFile(path.join(tempDir, iconFile)); + + fs.writeFileSync(path.join(tempDir, 'package.json'), JSON.stringify({ + name: config.extensionName, + version: packageJson.version, + private: true, + type: 'module' + }, null, 2) + '\n'); + + fs.writeFileSync(path.join(tempDir, 'manifest.json'), JSON.stringify({ + manifest_version: '0.3', + name: config.extensionName, + display_name: config.displayName, + version: packageJson.version, + description: config.description, + long_description: config.longDescription, + author: { + name: 'Adobe', + url: 'https://www.adobe.com' + }, + repository: { + type: 'git', + url: 'https://github.com/adobe/react-spectrum' + }, + homepage: config.homepage, + documentation: config.documentation, + support: 'https://github.com/adobe/react-spectrum/issues', + icon: iconFile, + license: 'Apache-2.0', + keywords: config.keywords, + privacy_policies: ['https://www.adobe.com/privacy/policy.html'], + tools: config.tools, + compatibility: { + platforms: ['darwin', 'win32', 'linux'], + runtimes: { + node: '>=18' + } + }, + server: { + type: 'node', + entry_point: config.serverEntryPoint, + mcp_config: { + command: 'node', + args: [`\${__dirname}/${config.serverEntryPoint}`] + } + } + }, null, 2) + '\n'); + + fs.mkdirSync(config.outputDir, {recursive: true}); + const outputPath = path.join(config.outputDir, config.outputFile); + runMcpbCli(['validate', tempDir]); + runMcpbCli(['pack', tempDir, outputPath]); + + const sizeKb = (fs.statSync(outputPath).size / 1024).toFixed(1); + console.log(`Generated ${config.outputFile} (${sizeKb} kB)`); + } finally { + fs.rmSync(tempDir, {recursive: true, force: true}); + } +} + +function copyDependencyTree(packageName, outputNodeModulesDir, bundledPackages, fromDir = repoRoot) { + if (bundledPackages.has(packageName)) { + return; + } + + const packageDir = resolvePackageDir(packageName, fromDir); + const packageJsonPath = path.join(packageDir, 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); + bundledPackages.add(packageName); + + copyDirectory(packageDir, path.join(outputNodeModulesDir, packageName)); + + for (const dependency of Object.keys(packageJson.dependencies || {})) { + copyDependencyTree(dependency, outputNodeModulesDir, bundledPackages, packageDir); + } + + for (const dependency of Object.keys(packageJson.optionalDependencies || {})) { + copyDependencyTree(dependency, outputNodeModulesDir, bundledPackages, packageDir); + } +} + +function resolvePackageDir(packageName, fromDir) { + let currentDir = fromDir; + const root = path.parse(currentDir).root; + + while (true) { + const packageJsonPath = path.join(currentDir, 'node_modules', packageName, 'package.json'); + if (fs.existsSync(packageJsonPath)) { + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); + if (packageJson.name === packageName) { + return path.dirname(packageJsonPath); + } + } + + if (currentDir === root) { + break; + } + currentDir = path.dirname(currentDir); + } + + throw new Error(`Could not resolve the package directory for ${packageName}`); +} + +function copyDirectory(from, to) { + fs.mkdirSync(path.dirname(to), {recursive: true}); + fs.cpSync(from, to, { + recursive: true, + dereference: true + }); +} + +function runMcpbCli(args) { + const mcpbPackageDir = resolvePackageDir('@anthropic-ai/mcpb', repoRoot); + const cliPath = path.join(mcpbPackageDir, 'dist/cli/cli.js'); + if (!fs.existsSync(cliPath)) { + throw new Error(`Could not find MCPB CLI at ${cliPath}`); + } + + execFileSync(process.execPath, [cliPath, ...args], { + cwd: repoRoot, + stdio: 'inherit' + }); +} + +const targets = requestedLibraries.length > 0 ? requestedLibraries : Object.keys(libraries); + +for (const name of targets) { + if (!(name in libraries)) { + throw new Error(`Unknown MCP bundle target '${name}'. Expected one of: ${Object.keys(libraries).join(', ')}`); + } +} + +for (const name of targets) { + await generateBundle(name, libraries[name]); +} diff --git a/yarn.lock b/yarn.lock index 10bc876e12b..e51235255d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -151,6 +151,25 @@ __metadata: languageName: node linkType: hard +"@anthropic-ai/mcpb@npm:^2.1.2": + version: 2.1.2 + resolution: "@anthropic-ai/mcpb@npm:2.1.2" + dependencies: + "@inquirer/prompts": "npm:^6.0.1" + commander: "npm:^13.1.0" + fflate: "npm:^0.8.2" + galactus: "npm:^1.0.0" + ignore: "npm:^7.0.5" + node-forge: "npm:^1.3.2" + pretty-bytes: "npm:^5.6.0" + zod: "npm:^3.25.67" + zod-to-json-schema: "npm:^3.24.6" + bin: + mcpb: dist/cli/cli.js + checksum: 10c0/ac35923b9f43e6d1ad23e7e6035f38c42f86e87e4a125ff806f416d8b0e5482caafa22939c4b3e5d6c6ba75fa91c120c1c91e9e39e430ea8207ea96de9cb762a + languageName: node + linkType: hard + "@babel/cli@npm:7.24.1": version: 7.24.1 resolution: "@babel/cli@npm:7.24.1" @@ -2741,6 +2760,172 @@ __metadata: languageName: node linkType: hard +"@inquirer/checkbox@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/checkbox@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/figures": "npm:^1.0.6" + "@inquirer/type": "npm:^2.0.0" + ansi-escapes: "npm:^4.3.2" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/1e8c508772757000209b89e7d0455ac5a0684b3ba3c4b5def13d4da95b19bcab670458d77a18f5a5daeec273578d1c3b2072030221dbfa7e0738abd5c0bc4af4 + languageName: node + linkType: hard + +"@inquirer/confirm@npm:^4.0.1": + version: 4.0.1 + resolution: "@inquirer/confirm@npm:4.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + checksum: 10c0/8ea5e6a63efa348b626750384c249cc903280e38c2596bb42c640f178b375dbc389d8c4d040b2e4759b3937d8a188e245ca262b8dc7cdb2fa35dfce4104c2e8f + languageName: node + linkType: hard + +"@inquirer/core@npm:^9.2.1": + version: 9.2.1 + resolution: "@inquirer/core@npm:9.2.1" + dependencies: + "@inquirer/figures": "npm:^1.0.6" + "@inquirer/type": "npm:^2.0.0" + "@types/mute-stream": "npm:^0.0.4" + "@types/node": "npm:^22.5.5" + "@types/wrap-ansi": "npm:^3.0.0" + ansi-escapes: "npm:^4.3.2" + cli-width: "npm:^4.1.0" + mute-stream: "npm:^1.0.0" + signal-exit: "npm:^4.1.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^6.2.0" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/11c14be77a9fa85831de799a585721b0a49ab2f3b7d8fd1780c48ea2b29229c6bdc94e7892419086d0f7734136c2ba87b6a32e0782571eae5bbd655b1afad453 + languageName: node + linkType: hard + +"@inquirer/editor@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/editor@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + external-editor: "npm:^3.1.0" + checksum: 10c0/edff144ce57d5a0793ae9c2ac3d16934d120ba9b277187613a44923a0b7dc45ba8b7382f56b66cf730c050b58637b236a0f8b280add33bbc53de1e78a10240e7 + languageName: node + linkType: hard + +"@inquirer/expand@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/expand@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/384db4ac56bc68b56a83a6d164ce039b35addd64a8e422cb8605e38d0f54a3654b4d2e4463575c6ffc34e30bcad5c728c23d7cc7227f4eb440b50fe36f6a785c + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.6": + version: 1.0.15 + resolution: "@inquirer/figures@npm:1.0.15" + checksum: 10c0/6e39a040d260ae234ae220180b7994ff852673e20be925f8aa95e78c7934d732b018cbb4d0ec39e600a410461bcb93dca771e7de23caa10630d255692e440f69 + languageName: node + linkType: hard + +"@inquirer/input@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/input@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + checksum: 10c0/e8b9d4ad933e70737903606241e8d1f317d3d57719ce0a77e97a050bd1109310bed8df0787ad7913ea699baaeefc448b52989de0a7c3b87ded0a3e54052a60d0 + languageName: node + linkType: hard + +"@inquirer/number@npm:^2.0.1": + version: 2.0.1 + resolution: "@inquirer/number@npm:2.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + checksum: 10c0/560e34653693a940b6767e9071c8a361291636b47055f2847d7973e868afba87eedb999a60be0d78064f4481c091e64b913f4b9a84f2cd7a6774d65524bcccbc + languageName: node + linkType: hard + +"@inquirer/password@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/password@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + ansi-escapes: "npm:^4.3.2" + checksum: 10c0/0223ce3f4700a1fa1bc3827bca35d71001e5b41c7a59717e078834bf66345c8c6bba5704350c8ae237e681c30969241ae918dba2e033d01810acf7ffefacd4e6 + languageName: node + linkType: hard + +"@inquirer/prompts@npm:^6.0.1": + version: 6.0.1 + resolution: "@inquirer/prompts@npm:6.0.1" + dependencies: + "@inquirer/checkbox": "npm:^3.0.1" + "@inquirer/confirm": "npm:^4.0.1" + "@inquirer/editor": "npm:^3.0.1" + "@inquirer/expand": "npm:^3.0.1" + "@inquirer/input": "npm:^3.0.1" + "@inquirer/number": "npm:^2.0.1" + "@inquirer/password": "npm:^3.0.1" + "@inquirer/rawlist": "npm:^3.0.1" + "@inquirer/search": "npm:^2.0.1" + "@inquirer/select": "npm:^3.0.1" + checksum: 10c0/42fe55137531a2d18c24f910fec2d2f1a4b086ad3ad29e8b85aeb8b454ca8e132e463623f1b9e7ac5c60c58010970a923cec23ed94ff14dc23eef086e2641fca + languageName: node + linkType: hard + +"@inquirer/rawlist@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/rawlist@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/type": "npm:^2.0.0" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/1b2f0693ad8ae59d22c1dbec03518ee800af7553225cc1e7a7740b0eb2dd59c5c09705217fe2f9946b20c0221a4e3b2a17258a9cb496fd2eb5af0a0c9ac1cfca + languageName: node + linkType: hard + +"@inquirer/search@npm:^2.0.1": + version: 2.0.1 + resolution: "@inquirer/search@npm:2.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/figures": "npm:^1.0.6" + "@inquirer/type": "npm:^2.0.0" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/3d016b259304fa566961e64266af03e748486aa306c76326ef20893706e16019cb91fba32561dd4c2910718e4b7959107922c6485abc88aff49edf94a6e2c76a + languageName: node + linkType: hard + +"@inquirer/select@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/select@npm:3.0.1" + dependencies: + "@inquirer/core": "npm:^9.2.1" + "@inquirer/figures": "npm:^1.0.6" + "@inquirer/type": "npm:^2.0.0" + ansi-escapes: "npm:^4.3.2" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 10c0/83aa571dba12f69f267507230055d07279a7352ef032d6ea849eb32cd663f3e26aab2ce4fd5f59231f4c7624b92e7d40dd8eef5907431e81eb3d45d062c2cbb8 + languageName: node + linkType: hard + +"@inquirer/type@npm:^2.0.0": + version: 2.0.0 + resolution: "@inquirer/type@npm:2.0.0" + dependencies: + mute-stream: "npm:^1.0.0" + checksum: 10c0/8c663d52beb2b89a896d3c3d5cc3d6d024fa149e565555bcb42fa640cbe23fba7ff2c51445342cef1fe6e46305e2d16c1590fa1d11ad0ddf93a67b655ef41f0a + languageName: node + linkType: hard + "@internationalized/date@npm:^3.12.1, @internationalized/date@workspace:packages/@internationalized/date": version: 0.0.0-use.local resolution: "@internationalized/date@workspace:packages/@internationalized/date" @@ -7151,6 +7336,7 @@ __metadata: version: 0.0.0-use.local resolution: "@react-spectrum/s2-docs@workspace:packages/dev/s2-docs" dependencies: + "@anthropic-ai/mcpb": "npm:^2.1.2" "@babel/parser": "npm:^7.26.3" "@parcel/plugin": "npm:^2.16.3" "@parcel/rsc": "npm:^2.16.3" @@ -10007,6 +10193,24 @@ __metadata: languageName: node linkType: hard +"@types/mute-stream@npm:^0.0.4": + version: 0.0.4 + resolution: "@types/mute-stream@npm:0.0.4" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/944730fd7b398c5078de3c3d4d0afeec8584283bc694da1803fdfca14149ea385e18b1b774326f1601baf53898ce6d121a952c51eb62d188ef6fcc41f725c0dc + languageName: node + linkType: hard + +"@types/node@npm:^22.5.5": + version: 22.19.15 + resolution: "@types/node@npm:22.19.15" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/f17eaf3d0d1da5e93ad9e287efb78201f8a5282973c004c5f70d91675c5c6b926a23acaa7b158a42b3d7e27e36b349d65a531710c91c308fca53dd7fa280ef98 + languageName: node + linkType: hard + "@types/node@npm:^24": version: 24.10.9 resolution: "@types/node@npm:24.10.9" @@ -10117,6 +10321,13 @@ __metadata: languageName: node linkType: hard +"@types/wrap-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/wrap-ansi@npm:3.0.0" + checksum: 10c0/8d8f53363f360f38135301a06b596c295433ad01debd082078c33c6ed98b05a5c8fe8853a88265432126096084f4a135ec1564e3daad631b83296905509f90b3 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 13.1.0 resolution: "@types/yargs-parser@npm:13.1.0" @@ -11139,6 +11350,15 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^4.3.2": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: "npm:^0.21.3" + checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 + languageName: node + linkType: hard + "ansi-escapes@npm:^6.0.0": version: 6.2.0 resolution: "ansi-escapes@npm:6.2.0" @@ -12939,6 +13159,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f + languageName: node + linkType: hard + "client-only@npm:^0.0.1": version: 0.0.1 resolution: "client-only@npm:0.0.1" @@ -13205,6 +13432,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^13.1.0": + version: 13.1.0 + resolution: "commander@npm:13.1.0" + checksum: 10c0/7b8c5544bba704fbe84b7cab2e043df8586d5c114a4c5b607f83ae5060708940ed0b5bd5838cf8ce27539cde265c1cbd59ce3c8c6b017ed3eec8943e3a415164 + languageName: node + linkType: hard + "commander@npm:^3.0.2": version: 3.0.2 resolution: "commander@npm:3.0.2" @@ -16084,7 +16318,7 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3": +"external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" dependencies: @@ -16274,6 +16508,13 @@ __metadata: languageName: node linkType: hard +"fflate@npm:^0.8.2": + version: 0.8.2 + resolution: "fflate@npm:0.8.2" + checksum: 10c0/03448d630c0a583abea594835a9fdb2aaf7d67787055a761515bf4ed862913cfd693b4c4ffd5c3f3b355a70cf1e19033e9ae5aedcca103188aaff91b8bd6e293 + languageName: node + linkType: hard + "figgy-pudding@npm:^3.4.1, figgy-pudding@npm:^3.5.1": version: 3.5.1 resolution: "figgy-pudding@npm:3.5.1" @@ -16510,6 +16751,16 @@ __metadata: languageName: node linkType: hard +"flora-colossus@npm:^2.0.0": + version: 2.0.0 + resolution: "flora-colossus@npm:2.0.0" + dependencies: + debug: "npm:^4.3.4" + fs-extra: "npm:^10.1.0" + checksum: 10c0/ea50e6ff38fd089f536cbec57da9a3a311efe5a97c21a2c0ae8cc1a85a71c9301b10168693b6389e257c7dbccc3723cc4f0d98377e29b6b65e6f45a929fe5d54 + languageName: node + linkType: hard + "flow-parser@npm:0.*": version: 0.235.1 resolution: "flow-parser@npm:0.235.1" @@ -16714,6 +16965,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^10.1.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e + languageName: node + linkType: hard + "fs-extra@npm:^4.0.3": version: 4.0.3 resolution: "fs-extra@npm:4.0.3" @@ -16888,6 +17150,17 @@ __metadata: languageName: node linkType: hard +"galactus@npm:^1.0.0": + version: 1.0.0 + resolution: "galactus@npm:1.0.0" + dependencies: + debug: "npm:^4.3.4" + flora-colossus: "npm:^2.0.0" + fs-extra: "npm:^10.1.0" + checksum: 10c0/8422109720515f71b40c60275e05f0a65957bdf15498775ac610df9a254ffe36b10e31d239d88d60c2b348b86d213170d3cfa46562e89c8d860067a80b20ad46 + languageName: node + linkType: hard + "gauge@npm:~2.7.3": version: 2.7.4 resolution: "gauge@npm:2.7.4" @@ -18198,7 +18471,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^7.0.0": +"ignore@npm:^7.0.0, ignore@npm:^7.0.5": version: 7.0.5 resolution: "ignore@npm:7.0.5" checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d @@ -20360,6 +20633,19 @@ __metadata: languageName: node linkType: hard +"jsonfile@npm:^6.0.1": + version: 6.2.0 + resolution: "jsonfile@npm:6.2.0" + dependencies: + graceful-fs: "npm:^4.1.6" + universalify: "npm:^2.0.0" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/7f4f43b08d1869ded8a6822213d13ae3b99d651151d77efd1557ced0889c466296a7d9684e397bd126acf5eb2cfcb605808c3e681d0fdccd2fe5a04b47e76c0d + languageName: node + linkType: hard + "jsonparse@npm:^1.2.0": version: 1.3.1 resolution: "jsonparse@npm:1.3.1" @@ -22559,6 +22845,13 @@ __metadata: languageName: node linkType: hard +"mute-stream@npm:^1.0.0": + version: 1.0.0 + resolution: "mute-stream@npm:1.0.0" + checksum: 10c0/dce2a9ccda171ec979a3b4f869a102b1343dee35e920146776780de182f16eae459644d187e38d59a3d37adf85685e1c17c38cf7bfda7e39a9880f7a1d10a74c + languageName: node + linkType: hard + "mute-stream@npm:~0.0.4": version: 0.0.8 resolution: "mute-stream@npm:0.0.8" @@ -22745,6 +23038,13 @@ __metadata: languageName: node linkType: hard +"node-forge@npm:^1.3.2": + version: 1.4.0 + resolution: "node-forge@npm:1.4.0" + checksum: 10c0/67330a5f1f95257a4c8a93b7d555abe87b5f15e350123aa396c97a21a8ca94f9c6549008eb2c73668a91e0d7e3a905785acbd8f8bd0751c29401292011f8f8e1 + languageName: node + linkType: hard + "node-gyp-build-optional-packages@npm:5.0.7": version: 5.0.7 resolution: "node-gyp-build-optional-packages@npm:5.0.7" @@ -24473,6 +24773,13 @@ __metadata: languageName: node linkType: hard +"pretty-bytes@npm:^5.6.0": + version: 5.6.0 + resolution: "pretty-bytes@npm:5.6.0" + checksum: 10c0/f69f494dcc1adda98dbe0e4a36d301e8be8ff99bfde7a637b2ee2820e7cb583b0fc0f3a63b0e3752c01501185a5cf38602c7be60da41bdf84ef5b70e89c370f3 + languageName: node + linkType: hard + "pretty-format@npm:^27.0.2": version: 27.4.2 resolution: "pretty-format@npm:27.4.2" @@ -26716,7 +27023,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 @@ -28566,6 +28873,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 + languageName: node + linkType: hard + "type-fest@npm:^0.3.0": version: 0.3.1 resolution: "type-fest@npm:0.3.1" @@ -28854,6 +29168,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 + languageName: node + linkType: hard + "undici-types@npm:~7.16.0": version: 7.16.0 resolution: "undici-types@npm:7.16.0" @@ -29192,6 +29513,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a + languageName: node + linkType: hard + "unix-crypt-td-js@npm:1.1.4": version: 1.1.4 resolution: "unix-crypt-td-js@npm:1.1.4" @@ -30650,6 +30978,13 @@ __metadata: languageName: node linkType: hard +"yoctocolors-cjs@npm:^2.1.2": + version: 2.1.3 + resolution: "yoctocolors-cjs@npm:2.1.3" + checksum: 10c0/584168ef98eb5d913473a4858dce128803c4a6cd87c0f09e954fa01126a59a33ab9e513b633ad9ab953786ed16efdd8c8700097a51635aafaeed3fef7712fa79 + languageName: node + linkType: hard + "yoga-layout@npm:^3.2.1": version: 3.2.1 resolution: "yoga-layout@npm:3.2.1" @@ -30666,6 +31001,15 @@ __metadata: languageName: node linkType: hard +"zod-to-json-schema@npm:^3.24.6": + version: 3.25.2 + resolution: "zod-to-json-schema@npm:3.25.2" + peerDependencies: + zod: ^3.25.28 || ^4 + checksum: 10c0/dd300554393903022487688af14fbda5c719ba8179702bb55b3aa86318830467f0f7beb7d654036975ac963dc4843b72e59636448bfff9a0608f277bb6a14939 + languageName: node + linkType: hard + "zod-validation-error@npm:^3.0.3 || ^4.0.0": version: 4.0.2 resolution: "zod-validation-error@npm:4.0.2" @@ -30682,7 +31026,7 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.23.8": +"zod@npm:^3.23.8, zod@npm:^3.25.67": version: 3.25.76 resolution: "zod@npm:3.25.76" checksum: 10c0/5718ec35e3c40b600316c5b4c5e4976f7fee68151bc8f8d90ec18a469be9571f072e1bbaace10f1e85cf8892ea12d90821b200e980ab46916a6166a4260a983c