diff --git a/examples/basic-host/src/implementation.ts b/examples/basic-host/src/implementation.ts index b77b8af..f923737 100644 --- a/examples/basic-host/src/implementation.ts +++ b/examples/basic-host/src/implementation.ts @@ -271,7 +271,7 @@ export function newAppBridge( updateModelContext: { text: {} }, }, { hostContext: { - containerDimensions: options?.containerDimensions ?? { maxHeight: 600 }, + containerDimensions: options?.containerDimensions ?? { maxHeight: 6000 }, displayMode: options?.displayMode ?? "inline", availableDisplayModes: ["inline", "fullscreen"], }, diff --git a/examples/basic-host/src/index.tsx b/examples/basic-host/src/index.tsx index baaa7bb..cbed7c7 100644 --- a/examples/basic-host/src/index.tsx +++ b/examples/basic-host/src/index.tsx @@ -422,7 +422,7 @@ function AppIFramePanel({ toolCallInfo, isDestroying, onTeardownComplete }: AppI onDisplayModeChange: setDisplayMode, }, { // Provide container dimensions - maxHeight for flexible sizing - containerDimensions: { maxHeight: 600 }, + containerDimensions: { maxHeight: 6000 }, displayMode: "inline", }); appBridgeRef.current = appBridge; diff --git a/examples/debug-server/.gitignore b/examples/debug-server/.gitignore new file mode 100644 index 0000000..b947077 --- /dev/null +++ b/examples/debug-server/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/examples/debug-server/README.md b/examples/debug-server/README.md new file mode 100644 index 0000000..89d9a7d --- /dev/null +++ b/examples/debug-server/README.md @@ -0,0 +1,55 @@ +# Debug Server + +A comprehensive testing/debugging tool for the MCP Apps SDK that exercises every capability, callback, and result format combination. + +## Tools + +### debug-tool + +Configurable tool for testing all result variations: + +| Parameter | Type | Default | Description | +| -------------------------- | ----------------------------------------------------------------------------------- | -------- | ------------------------------------------- | +| `contentType` | `"text"` \| `"image"` \| `"audio"` \| `"resource"` \| `"resourceLink"` \| `"mixed"` | `"text"` | Content block type to return | +| `multipleBlocks` | boolean | `false` | Return 3 content blocks | +| `includeStructuredContent` | boolean | `true` | Include structuredContent in result | +| `includeMeta` | boolean | `false` | Include \_meta in result | +| `largeInput` | string | - | Large text input (tests tool-input-partial) | +| `simulateError` | boolean | `false` | Return isError: true | +| `delayMs` | number | - | Delay before response (ms) | + +### debug-refresh + +App-only tool (hidden from model) for polling server state. Returns current timestamp and call counter. + +## App UI + +The debug app provides a dashboard with: + +- **Event Log**: Real-time log of all SDK events with filtering +- **Host Info**: Context, capabilities, container dimensions, styles +- **Callback Status**: Table of all callbacks with call counts +- **Actions**: Buttons to test every SDK method: + - Send messages (text/image) + - Logging (debug/info/warning/error) + - Model context updates + - Display mode requests + - Link opening + - Resize controls + - Server tool calls + - File operations + +## Usage + +```bash +# Build +npm run --workspace examples/debug-server build + +# Run standalone +npm run --workspace examples/debug-server serve + +# Run with all examples +npm start +``` + +Then open `http://localhost:8080/basic-host/` and select "Debug MCP App Server" from the dropdown. diff --git a/examples/debug-server/grid-cell.png b/examples/debug-server/grid-cell.png new file mode 100644 index 0000000..2f1814f Binary files /dev/null and b/examples/debug-server/grid-cell.png differ diff --git a/examples/debug-server/main.ts b/examples/debug-server/main.ts new file mode 100644 index 0000000..5aa8ddb --- /dev/null +++ b/examples/debug-server/main.ts @@ -0,0 +1,94 @@ +/** + * Entry point for running the MCP server. + * Run with: npx mcp-server-debug + * Or: node dist/index.js [--stdio] + */ + +/** + * Shared utilities for running MCP servers with Streamable HTTP transport. + */ + +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; +import cors from "cors"; +import type { Request, Response } from "express"; +import { createServer } from "./server.js"; + +export interface ServerOptions { + port: number; + name?: string; +} + +/** + * Starts an MCP server with Streamable HTTP transport in stateless mode. + * + * @param createServer - Factory function that creates a new McpServer instance per request. + * @param options - Server configuration options. + */ +export async function startServer( + createServer: () => McpServer, + options: ServerOptions, +): Promise { + const { port, name = "MCP Server" } = options; + + const app = createMcpExpressApp({ host: "0.0.0.0" }); + app.use(cors()); + + app.all("/mcp", async (req: Request, res: Response) => { + const server = createServer(); + const transport = new StreamableHTTPServerTransport({ + sessionIdGenerator: undefined, + }); + + res.on("close", () => { + transport.close().catch(() => {}); + server.close().catch(() => {}); + }); + + try { + await server.connect(transport); + await transport.handleRequest(req, res, req.body); + } catch (error) { + console.error("MCP error:", error); + if (!res.headersSent) { + res.status(500).json({ + jsonrpc: "2.0", + error: { code: -32603, message: "Internal server error" }, + id: null, + }); + } + } + }); + + const httpServer = app.listen(port, (err) => { + if (err) { + console.error("Failed to start server:", err); + process.exit(1); + } + console.log(`${name} listening on http://localhost:${port}/mcp`); + }); + + const shutdown = () => { + console.log("\nShutting down..."); + httpServer.close(() => process.exit(0)); + }; + + process.on("SIGINT", shutdown); + process.on("SIGTERM", shutdown); +} + +async function main() { + if (process.argv.includes("--stdio")) { + await createServer().connect(new StdioServerTransport()); + } else { + const port = parseInt(process.env.PORT ?? "3110", 10); + await startServer(createServer, { port, name: "Debug Server" }); + } +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/examples/debug-server/mcp-app.html b/examples/debug-server/mcp-app.html new file mode 100644 index 0000000..63c3444 --- /dev/null +++ b/examples/debug-server/mcp-app.html @@ -0,0 +1,210 @@ + + + + + + + Debug App + + +
+ +
+

+ Event Log +
+ + +
+

+
+
+ + +
+

+ Host Info + ▼ +

+
+
+
+

Context

+
+
+
+

Capabilities

+
+
+
+

Container

+
+
+
+

Styles Sample

+
+
+
+
+
+ + +
+

+ Callback Status + ▼ +

+
+ + + + + + + + + + +
CallbackRegisteredCountLast Payload
+
+
+ + +
+

+ Actions + ▼ +

+
+ +
+

Messages

+
+ + +
+
+ +
+
+ + +
+

Logging

+
+ +
+
+ + + + +
+
+ + +
+

Model Context

+
+ + +
+
+ + +
+
+ + +
+

Display Mode

+
+ + + +
+
+ + +
+

Links

+
+ + +
+
+ + +
+

Size

+
+ +
+
+ + + +
+
+ Current: measuring... +
+
+ + +
+

Server Tools

+
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+ +
+
+ +
+
+ +
+
+
+ + + diff --git a/examples/debug-server/package.json b/examples/debug-server/package.json new file mode 100644 index 0000000..226f7e3 --- /dev/null +++ b/examples/debug-server/package.json @@ -0,0 +1,42 @@ +{ + "name": "@modelcontextprotocol/server-debug", + "version": "0.4.1", + "type": "module", + "description": "Debug MCP App Server for testing all SDK capabilities", + "repository": { + "type": "git", + "url": "https://github.com/modelcontextprotocol/ext-apps", + "directory": "examples/debug-server" + }, + "license": "MIT", + "main": "server.ts", + "files": [ + "server.ts", + "dist" + ], + "scripts": { + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", + "watch": "cross-env INPUT=mcp-app.html vite build --watch", + "serve": "bun --watch main.ts", + "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'", + "prepublishOnly": "npm run build" + }, + "dependencies": { + "@modelcontextprotocol/ext-apps": "^0.4.1", + "@modelcontextprotocol/sdk": "^1.24.0", + "zod": "^4.1.13" + }, + "devDependencies": { + "@types/cors": "^2.8.19", + "@types/express": "^5.0.0", + "@types/node": "^22.0.0", + "concurrently": "^9.2.1", + "cors": "^2.8.5", + "cross-env": "^10.1.0", + "express": "^5.1.0", + "typescript": "^5.9.3", + "vite": "^6.0.0", + "vite-plugin-singlefile": "^2.3.0" + } +} diff --git a/examples/debug-server/screenshot.png b/examples/debug-server/screenshot.png new file mode 100644 index 0000000..869fec0 Binary files /dev/null and b/examples/debug-server/screenshot.png differ diff --git a/examples/debug-server/server.ts b/examples/debug-server/server.ts new file mode 100644 index 0000000..fd3452a --- /dev/null +++ b/examples/debug-server/server.ts @@ -0,0 +1,294 @@ +import { + registerAppResource, + registerAppTool, + RESOURCE_MIME_TYPE, +} from "@modelcontextprotocol/ext-apps/server"; +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { + CallToolResult, + ReadResourceResult, +} from "@modelcontextprotocol/sdk/types.js"; +import fs from "node:fs/promises"; +import { appendFileSync } from "node:fs"; +import path from "node:path"; +import { z } from "zod"; + +// Works both from source (server.ts) and compiled (dist/server.js) +const DIST_DIR = import.meta.filename.endsWith(".ts") + ? path.join(import.meta.dirname, "dist") + : import.meta.dirname; + +// Track call counter across requests (stateful for demo purposes) +let callCounter = 0; + +// Parse --log-file argument or use default +const DEFAULT_LOG_FILE = "/tmp/mcp-apps-debug-server.log"; +function getLogFilePath(): string { + const logFileArg = process.argv.find((arg) => arg.startsWith("--log-file=")); + if (logFileArg) { + return logFileArg.split("=")[1]; + } + return process.env.DEBUG_LOG_FILE ?? DEFAULT_LOG_FILE; +} + +const logFilePath = getLogFilePath(); + +/** + * Append a log entry to the log file + */ +function appendToLogFile(entry: { + timestamp: string; + type: string; + payload: unknown; +}): void { + try { + const line = JSON.stringify(entry) + "\n"; + appendFileSync(logFilePath, line, "utf-8"); + } catch (e) { + console.error("[debug-server] Failed to write to log file:", e); + } +} + +// Minimal 1x1 blue PNG (base64) +const BLUE_PNG_1X1 = + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg=="; + +// Minimal silent WAV (base64) - 44 byte header + 1 sample +const SILENT_WAV = + "UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAAAAA=="; + +/** + * Input schema for the debug-tool + */ +const DebugInputSchema = z.object({ + // Content configuration + contentType: z + .enum(["text", "image", "audio", "resource", "resourceLink", "mixed"]) + .default("text"), + multipleBlocks: z.boolean().default(true), + includeStructuredContent: z.boolean().default(true), + includeMeta: z.boolean().default(true), + + // Streaming test (large input) + largeInput: z.string().optional(), + + // Error/delay simulation + simulateError: z.boolean().default(false), + delayMs: z.number().optional(), +}); + +type DebugInput = z.infer; + +/** + * Output schema for structured content + */ +const DebugOutputSchema = z.object({ + config: z.record(z.string(), z.unknown()), + timestamp: z.string(), + counter: z.number(), + largeInputLength: z.number().optional(), +}); + +/** + * Builds content blocks based on configuration + */ +function buildContent(args: DebugInput): CallToolResult["content"] { + const count = args.multipleBlocks ? 3 : 1; + const content: CallToolResult["content"] = []; + + for (let i = 0; i < count; i++) { + const suffix = args.multipleBlocks ? ` #${i + 1}` : ""; + + switch (args.contentType) { + case "text": + content.push({ type: "text", text: `Debug text content${suffix}` }); + break; + case "image": + content.push({ + type: "image", + data: BLUE_PNG_1X1, + mimeType: "image/png", + }); + break; + case "audio": + content.push({ + type: "audio", + data: SILENT_WAV, + mimeType: "audio/wav", + }); + break; + case "resource": + content.push({ + type: "resource", + resource: { + uri: `debug://embedded-resource${suffix.replace(/\s/g, "-")}`, + text: `Embedded resource content${suffix}`, + mimeType: "text/plain", + }, + }); + break; + case "resourceLink": + content.push({ + type: "resource_link", + uri: `debug://linked-resource${suffix.replace(/\s/g, "-")}`, + name: `Linked Resource${suffix}`, + mimeType: "text/plain", + }); + break; + case "mixed": + // Return one of each type (ignore multipleBlocks for mixed) + return [ + { type: "text", text: "Mixed content: text block" }, + { type: "image", data: BLUE_PNG_1X1, mimeType: "image/png" }, + { type: "audio", data: SILENT_WAV, mimeType: "audio/wav" }, + ]; + } + } + + return content; +} + +/** + * Creates a new MCP server instance with debug tools registered. + */ +export function createServer(): McpServer { + const server = new McpServer({ + name: "Debug MCP App Server", + version: "1.0.0", + }); + + const resourceUri = "ui://debug-tool/mcp-app.html"; + + // Main debug tool - exercises all result variations + registerAppTool( + server, + "debug-tool", + { + title: "Debug Tool", + description: + "Comprehensive debug tool for testing MCP Apps SDK. Configure content types, error simulation, delays, and more.", + inputSchema: DebugInputSchema, + outputSchema: DebugOutputSchema, + _meta: { ui: { resourceUri } }, + }, + async (args): Promise => { + // Apply delay if requested + if (args.delayMs && args.delayMs > 0) { + await new Promise((resolve) => setTimeout(resolve, args.delayMs)); + } + + // Build content based on config + const content = buildContent(args); + + // Build result + const result: CallToolResult = { content }; + + // Add structured content if requested + if (args.includeStructuredContent) { + result.structuredContent = { + config: args, + timestamp: new Date().toISOString(), + counter: ++callCounter, + ...(args.largeInput + ? { largeInputLength: args.largeInput.length } + : {}), + }; + } + + // Add _meta if requested + if (args.includeMeta) { + result._meta = { + debugInfo: { + processedAt: Date.now(), + serverVersion: "1.0.0", + }, + }; + } + + // Set error flag if requested + if (args.simulateError) { + result.isError = true; + } + + return result; + }, + ); + + // App-only refresh tool (hidden from model) + registerAppTool( + server, + "debug-refresh", + { + title: "Refresh Debug Info", + description: + "App-only tool for polling server state. Not visible to the model.", + inputSchema: z.object({}), + outputSchema: z.object({ timestamp: z.string(), counter: z.number() }), + _meta: { + ui: { + resourceUri, + visibility: ["app"], + }, + }, + }, + async (): Promise => { + const timestamp = new Date().toISOString(); + return { + content: [{ type: "text", text: `Server timestamp: ${timestamp}` }], + structuredContent: { timestamp, counter: callCounter }, + }; + }, + ); + + // App-only log tool - writes events to log file + registerAppTool( + server, + "debug-log", + { + title: "Log to File", + description: + "App-only tool for logging events to the server log file. Not visible to the model.", + inputSchema: z.object({ + type: z.string(), + payload: z.unknown(), + }), + outputSchema: z.object({ logged: z.boolean(), logFile: z.string() }), + _meta: { + ui: { + resourceUri, + visibility: ["app"], + }, + }, + }, + async (args): Promise => { + const timestamp = new Date().toISOString(); + appendToLogFile({ timestamp, type: args.type, payload: args.payload }); + return { + content: [{ type: "text", text: `Logged to ${logFilePath}` }], + structuredContent: { logged: true, logFile: logFilePath }, + }; + }, + ); + + // Register the resource which returns the bundled HTML/JavaScript for the UI + registerAppResource( + server, + resourceUri, + resourceUri, + { mimeType: RESOURCE_MIME_TYPE }, + async (): Promise => { + const html = await fs.readFile( + path.join(DIST_DIR, "mcp-app.html"), + "utf-8", + ); + + return { + contents: [ + { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html }, + ], + }; + }, + ); + + return server; +} diff --git a/examples/debug-server/src/global.css b/examples/debug-server/src/global.css new file mode 100644 index 0000000..1886326 --- /dev/null +++ b/examples/debug-server/src/global.css @@ -0,0 +1,33 @@ +* { + box-sizing: border-box; +} + +html, body { + font-family: system-ui, -apple-system, sans-serif; + font-size: 14px; + margin: 0; + padding: 0; +} + +code { + font-family: ui-monospace, "SF Mono", Monaco, "Cascadia Code", Consolas, monospace; + font-size: 0.9em; + background: rgba(0, 0, 0, 0.05); + padding: 0.1em 0.3em; + border-radius: 3px; +} + +@media (prefers-color-scheme: dark) { + code { + background: rgba(255, 255, 255, 0.1); + } +} + +button { + cursor: pointer; +} + +input, select, button { + font-family: inherit; + font-size: inherit; +} diff --git a/examples/debug-server/src/mcp-app.css b/examples/debug-server/src/mcp-app.css new file mode 100644 index 0000000..79a74ed --- /dev/null +++ b/examples/debug-server/src/mcp-app.css @@ -0,0 +1,367 @@ +.main { + --color-primary: #2563eb; + --color-primary-hover: #1d4ed8; + --color-success: #16a34a; + --color-warning: #ca8a04; + --color-error: #dc2626; + --color-border: #e5e7eb; + --color-bg-subtle: #f9fafb; + + width: 100%; + max-width: 800px; + padding: 1rem; + margin: 0 auto; +} + +@media (prefers-color-scheme: dark) { + .main { + --color-border: #374151; + --color-bg-subtle: #1f2937; + } +} + +/* Section styling */ +.section { + border: 1px solid var(--color-border); + border-radius: 8px; + margin-bottom: 1rem; + overflow: hidden; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem 1rem; + margin: 0; + font-size: 1rem; + font-weight: 600; + background: var(--color-bg-subtle); + border-bottom: 1px solid var(--color-border); +} + +.collapsible .section-header { + cursor: pointer; + user-select: none; +} + +.collapsible .section-header:hover { + background: var(--color-border); +} + +.toggle-icon { + transition: transform 0.2s; +} + +.collapsed .toggle-icon { + transform: rotate(-90deg); +} + +.collapsed .section-content { + display: none; +} + +.section-content { + padding: 1rem; +} + +.header-actions { + display: flex; + gap: 0.5rem; + align-items: center; +} + +/* Event log */ +.event-log { + max-height: 200px; + overflow-y: auto; + padding: 0.5rem; + font-family: ui-monospace, monospace; + font-size: 0.85rem; + background: var(--color-bg-subtle); +} + +.log-entry { + padding: 0.25rem 0; + border-bottom: 1px solid var(--color-border); + cursor: pointer; +} + +.log-entry:hover { + background: var(--color-bg-hover, rgba(0, 0, 0, 0.03)); +} + +.log-entry:last-child { + border-bottom: none; +} + +.log-entry-header { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.log-toggle { + color: #9ca3af; + font-size: 0.7rem; + width: 1rem; + transition: transform 0.15s ease; + user-select: none; +} + +.log-entry.expanded .log-toggle { + transform: rotate(90deg); +} + +.log-time { + color: #6b7280; + margin-right: 0.5rem; +} + +.log-type { + font-weight: 600; + margin-right: 0.5rem; +} + +.log-type.ontoolinput { color: var(--color-primary); } +.log-type.ontoolinputpartial { color: #8b5cf6; } +.log-type.ontoolresult { color: var(--color-success); } +.log-type.ontoolcancelled { color: var(--color-warning); } +.log-type.onhostcontextchanged { color: #7c3aed; } +.log-type.onteardown { color: #f97316; } +.log-type.oncalltool { color: #ec4899; } +.log-type.onlisttools { color: #14b8a6; } +.log-type.onerror { color: var(--color-error); } +.log-type.connected { color: var(--color-success); } +.log-type.update-context { color: #0891b2; } + +.log-payload-preview { + color: #6b7280; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; +} + +.log-payload-full { + display: none; + margin: 0.5rem 0 0.25rem 1.25rem; + padding: 0.5rem; + background: var(--color-bg-subtle, #f3f4f6); + border-radius: 4px; + font-size: 0.8rem; + overflow-x: auto; + white-space: pre-wrap; + word-break: break-all; + max-height: 300px; + overflow-y: auto; +} + +.log-entry.expanded .log-payload-full { + display: block; +} + +/* Info grid */ +.info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1rem; +} + +.info-group h3 { + margin: 0 0 0.5rem 0; + font-size: 0.9rem; + color: #6b7280; +} + +.info-group dl { + margin: 0; + font-size: 0.85rem; +} + +.info-group dt { + font-weight: 600; + color: #374151; +} + +.info-group dd { + margin: 0 0 0.5rem 0; + color: #6b7280; +} + +@media (prefers-color-scheme: dark) { + .info-group dt { color: #d1d5db; } + .info-group dd { color: #9ca3af; } +} + +.styles-sample { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.style-swatch { + width: 24px; + height: 24px; + border-radius: 4px; + border: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + color: white; + text-shadow: 0 0 2px black; +} + +/* Callback table */ +.callback-table { + width: 100%; + border-collapse: collapse; + font-size: 0.85rem; +} + +.callback-table th, +.callback-table td { + padding: 0.5rem; + text-align: left; + border-bottom: 1px solid var(--color-border); +} + +.callback-table th { + background: var(--color-bg-subtle); + font-weight: 600; +} + +.callback-table .registered-yes { + color: var(--color-success); +} + +.callback-table .registered-no { + color: #9ca3af; +} + +.callback-table .payload-preview { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; + font-family: ui-monospace, monospace; + font-size: 0.8rem; +} + +.callback-table .payload-preview:hover { + white-space: normal; + word-break: break-all; +} + +/* Action groups */ +.action-group { + margin-bottom: 1.5rem; +} + +.action-group:last-child { + margin-bottom: 0; +} + +.action-group h3 { + margin: 0 0 0.75rem 0; + font-size: 0.9rem; + font-weight: 600; + color: #374151; + border-bottom: 1px solid var(--color-border); + padding-bottom: 0.25rem; +} + +@media (prefers-color-scheme: dark) { + .action-group h3 { color: #d1d5db; } +} + +.action-row { + display: flex; + gap: 0.5rem; + align-items: center; + margin-bottom: 0.5rem; +} + +.action-row:last-child { + margin-bottom: 0; +} + +.action-row input[type="text"], +.action-row input[type="url"], +.action-row input[type="number"] { + flex: 1; + padding: 0.5rem; + border: 1px solid var(--color-border); + border-radius: 4px; + background: transparent; +} + +.action-row input[type="file"] { + flex: 1; +} + +.action-row button { + padding: 0.5rem 1rem; + border: none; + border-radius: 4px; + background: var(--color-primary); + color: white; + font-weight: 500; +} + +.action-row button:hover { + background: var(--color-primary-hover); +} + +.btn-row { + flex-wrap: wrap; +} + +.btn-small { + padding: 0.375rem 0.75rem !important; + font-size: 0.85rem; +} + +/* Tool config */ +.tool-config { + background: var(--color-bg-subtle); + padding: 0.75rem; + border-radius: 4px; + margin-bottom: 0.75rem; +} + +.config-row { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.config-row:last-child { + margin-bottom: 0; +} + +.config-row label { + min-width: 120px; + font-size: 0.85rem; +} + +.config-row select, +.config-row input[type="number"] { + padding: 0.25rem 0.5rem; + border: 1px solid var(--color-border); + border-radius: 4px; + background: transparent; +} + +/* Filter select */ +#log-filter { + padding: 0.25rem 0.5rem; + border: 1px solid var(--color-border); + border-radius: 4px; + background: transparent; + font-size: 0.85rem; +} diff --git a/examples/debug-server/src/mcp-app.ts b/examples/debug-server/src/mcp-app.ts new file mode 100644 index 0000000..b1c862d --- /dev/null +++ b/examples/debug-server/src/mcp-app.ts @@ -0,0 +1,642 @@ +/** + * @file Debug App - Comprehensive testing/debugging tool for the MCP Apps SDK. + * + * This app exercises every capability, callback, and result format combination. + */ +import { App, type McpUiHostContext } from "@modelcontextprotocol/ext-apps"; +import "./global.css"; +import "./mcp-app.css"; + +// ============================================================================ +// Types +// ============================================================================ + +interface LogEntry { + time: number; + type: string; + payload: unknown; +} + +interface AppState { + eventLog: LogEntry[]; + callbackCounts: Map; + lastPayloads: Map; + autoResizeCleanup: (() => void) | null; + logFilter: string; +} + +// ============================================================================ +// State +// ============================================================================ + +const state: AppState = { + eventLog: [], + callbackCounts: new Map(), + lastPayloads: new Map(), + autoResizeCleanup: null, + logFilter: "all", +}; + +// Callbacks we track +const CALLBACKS = [ + "ontoolinput", + "ontoolinputpartial", + "ontoolresult", + "ontoolcancelled", + "onhostcontextchanged", + "onteardown", + "oncalltool", + "onlisttools", + "onerror", +] as const; + +// ============================================================================ +// DOM Elements +// ============================================================================ + +const mainEl = document.querySelector(".main") as HTMLElement; +const eventLogEl = document.getElementById("event-log")!; +const logFilterEl = document.getElementById("log-filter") as HTMLSelectElement; +const clearLogBtn = document.getElementById("clear-log-btn")!; + +// Host info +const hostContextInfoEl = document.getElementById("host-context-info")!; +const hostCapabilitiesInfoEl = document.getElementById( + "host-capabilities-info", +)!; +const hostContainerInfoEl = document.getElementById("host-container-info")!; +const hostStylesSampleEl = document.getElementById("host-styles-sample")!; + +// Callback status +const callbackTableBodyEl = document.getElementById("callback-table-body")!; + +// Action elements +const messageTextEl = document.getElementById( + "message-text", +) as HTMLInputElement; +const sendMessageTextBtn = document.getElementById("send-message-text-btn")!; +const sendMessageImageBtn = document.getElementById("send-message-image-btn")!; + +const logDataEl = document.getElementById("log-data") as HTMLInputElement; +const logDebugBtn = document.getElementById("log-debug-btn")!; +const logInfoBtn = document.getElementById("log-info-btn")!; +const logWarningBtn = document.getElementById("log-warning-btn")!; +const logErrorBtn = document.getElementById("log-error-btn")!; + +const contextTextEl = document.getElementById( + "context-text", +) as HTMLInputElement; +const updateContextTextBtn = document.getElementById( + "update-context-text-btn", +)!; +const updateContextStructuredBtn = document.getElementById( + "update-context-structured-btn", +)!; +const updateContextImageBtn = document.getElementById( + "update-context-image-btn", +)!; + +const displayInlineBtn = document.getElementById("display-inline-btn")!; +const displayFullscreenBtn = document.getElementById("display-fullscreen-btn")!; +const displayPipBtn = document.getElementById("display-pip-btn")!; + +const linkUrlEl = document.getElementById("link-url") as HTMLInputElement; +const openLinkBtn = document.getElementById("open-link-btn")!; + +const autoResizeToggleEl = document.getElementById( + "auto-resize-toggle", +) as HTMLInputElement; +const resize200x100Btn = document.getElementById("resize-200x100-btn")!; +const resize400x300Btn = document.getElementById("resize-400x300-btn")!; +const resize800x600Btn = document.getElementById("resize-800x600-btn")!; +const currentSizeEl = document.getElementById("current-size")!; + +// Tool config elements +const toolContentTypeEl = document.getElementById( + "tool-content-type", +) as HTMLSelectElement; +const toolMultipleBlocksEl = document.getElementById( + "tool-multiple-blocks", +) as HTMLInputElement; +const toolStructuredContentEl = document.getElementById( + "tool-structured-content", +) as HTMLInputElement; +const toolIncludeMetaEl = document.getElementById( + "tool-include-meta", +) as HTMLInputElement; +const toolSimulateErrorEl = document.getElementById( + "tool-simulate-error", +) as HTMLInputElement; +const toolDelayMsEl = document.getElementById( + "tool-delay-ms", +) as HTMLInputElement; +const callDebugToolBtn = document.getElementById("call-debug-tool-btn")!; +const callDebugRefreshBtn = document.getElementById("call-debug-refresh-btn")!; + +// ============================================================================ +// Utility Functions +// ============================================================================ + +function formatTime(timestamp: number): string { + const date = new Date(timestamp); + const h = date.getHours().toString().padStart(2, "0"); + const m = date.getMinutes().toString().padStart(2, "0"); + const s = date.getSeconds().toString().padStart(2, "0"); + const ms = date.getMilliseconds().toString().padStart(3, "0"); + return `${h}:${m}:${s}.${ms}`; +} + +function truncatePayload(payload: unknown): string { + const str = JSON.stringify(payload); + if (str.length > 100) { + return str.slice(0, 100) + "..."; + } + return str; +} + +// ============================================================================ +// Rendering Functions +// ============================================================================ + +function renderEventLog(): void { + const filtered = + state.logFilter === "all" + ? state.eventLog + : state.eventLog.filter((e) => e.type === state.logFilter); + + const fullPayload = (payload: unknown) => + JSON.stringify(payload, null, 2) + .replace(//g, ">"); + + eventLogEl.innerHTML = filtered + .map( + (entry, index) => ` +
+
+ ▶ + [${formatTime(entry.time)}] + ${entry.type}: + ${truncatePayload(entry.payload)} +
+
${fullPayload(entry.payload)}
+
+ `, + ) + .join(""); + + // Add click handlers for toggling + eventLogEl.querySelectorAll(".log-entry").forEach((el) => { + el.addEventListener("click", () => { + el.classList.toggle("expanded"); + }); + }); + + // Auto-scroll to bottom + eventLogEl.scrollTop = eventLogEl.scrollHeight; +} + +function renderCallbackStatus(): void { + callbackTableBodyEl.innerHTML = CALLBACKS.map((name) => { + const count = state.callbackCounts.get(name) ?? 0; + const lastPayload = state.lastPayloads.get(name); + const registered = name !== "onerror"; // All callbacks are registered + + return ` + + ${name} + ${registered ? "✓" : "✗"} + ${count} + ${lastPayload ? truncatePayload(lastPayload) : "-"} + + `; + }).join(""); +} + +function renderHostInfo(): void { + const ctx = app.getHostContext(); + const caps = app.getHostCapabilities(); + const version = app.getHostVersion(); + + // Context info + if (ctx) { + hostContextInfoEl.innerHTML = ` +
Theme
${ctx.theme ?? "unknown"}
+
Locale
${ctx.locale ?? "unknown"}
+
TimeZone
${ctx.timeZone ?? "unknown"}
+
Platform
${ctx.platform ?? "unknown"}
+
Display Mode
${ctx.displayMode ?? "unknown"}
+
Host
${version?.name ?? "unknown"} v${version?.version ?? "?"}
+ `; + } else { + hostContextInfoEl.innerHTML = "
No context available
"; + } + + // Capabilities + if (caps) { + hostCapabilitiesInfoEl.innerHTML = ` +
openLinks
${caps.openLinks ? "✓" : "✗"}
+
serverTools
${caps.serverTools ? "✓" : "✗"}
+
serverResources
${caps.serverResources ? "✓" : "✗"}
+
logging
${caps.logging ? "✓" : "✗"}
+
message
${caps.message ? "✓" : "✗"}
+
updateModelContext
${caps.updateModelContext ? "✓" : "✗"}
+ `; + } else { + hostCapabilitiesInfoEl.innerHTML = "
No capabilities available
"; + } + + // Container info + if (ctx?.containerDimensions) { + const dims = ctx.containerDimensions; + hostContainerInfoEl.innerHTML = ` +
Width
${"width" in dims ? dims.width + "px" : `max ${dims.maxWidth ?? "?"}px`}
+
Height
${"height" in dims ? dims.height + "px" : `max ${dims.maxHeight ?? "?"}px`}
+
Safe Area
${ctx.safeAreaInsets ? `T${ctx.safeAreaInsets.top} R${ctx.safeAreaInsets.right} B${ctx.safeAreaInsets.bottom} L${ctx.safeAreaInsets.left}` : "none"}
+ `; + } else { + hostContainerInfoEl.innerHTML = "
No container info
"; + } + + // Styles sample + if (ctx?.styles) { + const styleVars = Object.entries(ctx.styles).slice(0, 6); + hostStylesSampleEl.innerHTML = styleVars + .map(([key, value]) => { + const color = String(value); + return `
`; + }) + .join(""); + } else { + hostStylesSampleEl.innerHTML = "No styles"; + } +} + +function updateCurrentSize(): void { + const w = document.documentElement.scrollWidth; + const h = document.documentElement.scrollHeight; + currentSizeEl.textContent = `${w}x${h}`; +} + +// ============================================================================ +// Event Logging +// ============================================================================ + +/** + * Send a log entry to the server's debug-log tool (writes to file) + */ +async function sendToServerLog(type: string, payload: unknown): Promise { + try { + await app.callServerTool({ + name: "debug-log", + arguments: { type, payload }, + }); + } catch (e) { + // Log to console only - don't call logEvent to avoid infinite loop + console.error("[debug-app] Failed to send log to server:", e); + } +} + +function logEvent(type: string, payload: unknown): void { + const time = Date.now(); + + // Log to console + console.log(`[debug-app] ${type}:`, payload); + + // Update state + const count = (state.callbackCounts.get(type) ?? 0) + 1; + state.callbackCounts.set(type, count); + state.lastPayloads.set(type, payload); + state.eventLog.push({ time, type, payload }); + + // Keep log manageable (max 100 entries) + if (state.eventLog.length > 100) { + state.eventLog.shift(); + } + + renderEventLog(); + renderCallbackStatus(); + + // Send to server log file (async, fire-and-forget) + // Skip sending debug-log results to avoid noise + if ( + type !== "server-tool-result" || + (payload as { name?: string })?.name !== "debug-log" + ) { + sendToServerLog(type, payload); + } +} + +// ============================================================================ +// Safe Area Handling +// ============================================================================ + +function handleHostContextChanged(ctx: McpUiHostContext): void { + if (ctx.safeAreaInsets) { + mainEl.style.paddingTop = `${ctx.safeAreaInsets.top}px`; + mainEl.style.paddingRight = `${ctx.safeAreaInsets.right}px`; + mainEl.style.paddingBottom = `${ctx.safeAreaInsets.bottom}px`; + mainEl.style.paddingLeft = `${ctx.safeAreaInsets.left}px`; + } + renderHostInfo(); +} + +// ============================================================================ +// App Instance & Callbacks +// ============================================================================ + +const app = new App( + { name: "Debug App", version: "1.0.0" }, + { tools: { listChanged: true } }, // Declare tools capability for oncalltool/onlisttools + { autoResize: false }, // We'll manage auto-resize ourselves for toggle demo +); + +// Register ALL callbacks BEFORE connecting +app.ontoolinput = (params) => { + logEvent("ontoolinput", params); +}; + +app.ontoolinputpartial = (params) => { + logEvent("ontoolinputpartial", params); +}; + +app.ontoolresult = (result) => { + logEvent("ontoolresult", result); +}; + +app.ontoolcancelled = (params) => { + logEvent("ontoolcancelled", params); +}; + +app.onhostcontextchanged = (ctx) => { + logEvent("onhostcontextchanged", ctx); + handleHostContextChanged(ctx); +}; + +app.onteardown = async (params) => { + logEvent("onteardown", params); + return {}; +}; + +app.oncalltool = async (params) => { + logEvent("oncalltool", params); + return { + content: [{ type: "text", text: "App handled tool call" }], + }; +}; + +app.onlisttools = async (params) => { + logEvent("onlisttools", params); + return { tools: [] }; +}; + +app.onerror = (error) => { + logEvent("onerror", error); +}; + +// ============================================================================ +// Section Collapsing +// ============================================================================ + +document.querySelectorAll(".section-header[data-toggle]").forEach((header) => { + header.addEventListener("click", () => { + const section = header.closest(".section"); + section?.classList.toggle("collapsed"); + }); +}); + +// ============================================================================ +// Event Log Controls +// ============================================================================ + +logFilterEl.addEventListener("change", () => { + state.logFilter = logFilterEl.value; + renderEventLog(); +}); + +clearLogBtn.addEventListener("click", () => { + state.eventLog = []; + renderEventLog(); +}); + +// ============================================================================ +// Message Actions +// ============================================================================ + +sendMessageTextBtn.addEventListener("click", async () => { + try { + const result = await app.sendMessage({ + role: "user", + content: [{ type: "text", text: messageTextEl.value }], + }); + logEvent("send-message-result", result); + } catch (e) { + logEvent("error", e); + } +}); + +sendMessageImageBtn.addEventListener("click", async () => { + // 1x1 red PNG for testing + const redPng = + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=="; + try { + const result = await app.sendMessage({ + role: "user", + content: [{ type: "image", data: redPng, mimeType: "image/png" }], + }); + logEvent("send-message-result", result); + } catch (e) { + logEvent("error", e); + } +}); + +// ============================================================================ +// Logging Actions +// ============================================================================ + +function sendLog(level: "debug" | "info" | "warning" | "error"): void { + app.sendLog({ level, data: logDataEl.value }); + logEvent("send-log", { level, data: logDataEl.value }); +} + +logDebugBtn.addEventListener("click", () => sendLog("debug")); +logInfoBtn.addEventListener("click", () => sendLog("info")); +logWarningBtn.addEventListener("click", () => sendLog("warning")); +logErrorBtn.addEventListener("click", () => sendLog("error")); + +// ============================================================================ +// Model Context Actions +// ============================================================================ + +updateContextTextBtn.addEventListener("click", async () => { + try { + await app.updateModelContext({ + content: [{ type: "text", text: contextTextEl.value }], + }); + logEvent("update-context", { type: "text", value: contextTextEl.value }); + } catch (e) { + logEvent("error", e); + } +}); + +updateContextStructuredBtn.addEventListener("click", async () => { + try { + await app.updateModelContext({ + structuredContent: { + debugState: { + eventCount: state.eventLog.length, + timestamp: new Date().toISOString(), + }, + }, + }); + logEvent("update-context", { type: "structured" }); + } catch (e) { + logEvent("error", e); + } +}); + +updateContextImageBtn.addEventListener("click", async () => { + // 1x1 red PNG for testing + const redPng = + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=="; + try { + await app.updateModelContext({ + content: [{ type: "image", data: redPng, mimeType: "image/png" }], + }); + logEvent("update-context", { type: "image" }); + } catch (e) { + logEvent("error", e); + } +}); + +// ============================================================================ +// Display Mode Actions +// ============================================================================ + +async function requestDisplayMode( + mode: "inline" | "fullscreen" | "pip", +): Promise { + try { + const result = await app.requestDisplayMode({ mode }); + logEvent("display-mode-result", { mode, result }); + } catch (e) { + logEvent("error", e); + } +} + +displayInlineBtn.addEventListener("click", () => requestDisplayMode("inline")); +displayFullscreenBtn.addEventListener("click", () => + requestDisplayMode("fullscreen"), +); +displayPipBtn.addEventListener("click", () => requestDisplayMode("pip")); + +// ============================================================================ +// Link Action +// ============================================================================ + +openLinkBtn.addEventListener("click", async () => { + try { + const result = await app.openLink({ url: linkUrlEl.value }); + logEvent("open-link-result", result); + } catch (e) { + logEvent("error", e); + } +}); + +// ============================================================================ +// Size Controls +// ============================================================================ + +autoResizeToggleEl.addEventListener("change", () => { + if (autoResizeToggleEl.checked) { + if (!state.autoResizeCleanup) { + state.autoResizeCleanup = app.setupSizeChangedNotifications(); + } + } else { + if (state.autoResizeCleanup) { + state.autoResizeCleanup(); + state.autoResizeCleanup = null; + } + } + logEvent("auto-resize-toggle", { enabled: autoResizeToggleEl.checked }); +}); + +function manualResize(width: number, height: number): void { + app.sendSizeChanged({ width, height }); + logEvent("manual-resize", { width, height }); +} + +resize200x100Btn.addEventListener("click", () => manualResize(200, 100)); +resize400x300Btn.addEventListener("click", () => manualResize(400, 300)); +resize800x600Btn.addEventListener("click", () => manualResize(800, 600)); + +// Update current size periodically +setInterval(updateCurrentSize, 1000); + +// ============================================================================ +// Server Tool Actions +// ============================================================================ + +callDebugToolBtn.addEventListener("click", async () => { + const args = { + contentType: toolContentTypeEl.value, + multipleBlocks: toolMultipleBlocksEl.checked, + includeStructuredContent: toolStructuredContentEl.checked, + includeMeta: toolIncludeMetaEl.checked, + simulateError: toolSimulateErrorEl.checked, + delayMs: parseInt(toolDelayMsEl.value, 10) || undefined, + }; + + try { + logEvent("call-server-tool", { name: "debug-tool", arguments: args }); + const result = await app.callServerTool({ + name: "debug-tool", + arguments: args, + }); + logEvent("server-tool-result", result); + } catch (e) { + logEvent("error", e); + } +}); + +callDebugRefreshBtn.addEventListener("click", async () => { + try { + logEvent("call-server-tool", { name: "debug-refresh", arguments: {} }); + const result = await app.callServerTool({ + name: "debug-refresh", + arguments: {}, + }); + logEvent("server-tool-result", result); + } catch (e) { + logEvent("error", e); + } +}); + +// ============================================================================ +// Initialization +// ============================================================================ + +// Initial render +renderCallbackStatus(); + +// Connect to host +app + .connect() + .then(() => { + logEvent("connected", { success: true }); + + const ctx = app.getHostContext(); + if (ctx) { + handleHostContextChanged(ctx); + } + + renderHostInfo(); + updateCurrentSize(); + + // Auto-resize is enabled by default in App, capture cleanup if we want to toggle + // We'll set it up ourselves since we want toggle control + state.autoResizeCleanup = app.setupSizeChangedNotifications(); + }) + .catch((e) => { + logEvent("error", e); + }); diff --git a/examples/debug-server/tsconfig.json b/examples/debug-server/tsconfig.json new file mode 100644 index 0000000..535267b --- /dev/null +++ b/examples/debug-server/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src", "server.ts"] +} diff --git a/examples/debug-server/tsconfig.server.json b/examples/debug-server/tsconfig.server.json new file mode 100644 index 0000000..05ddd8e --- /dev/null +++ b/examples/debug-server/tsconfig.server.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "./dist", + "rootDir": ".", + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true + }, + "include": ["server.ts"] +} diff --git a/examples/debug-server/vite.config.ts b/examples/debug-server/vite.config.ts new file mode 100644 index 0000000..6ff6d99 --- /dev/null +++ b/examples/debug-server/vite.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from "vite"; +import { viteSingleFile } from "vite-plugin-singlefile"; + +const INPUT = process.env.INPUT; +if (!INPUT) { + throw new Error("INPUT environment variable is not set"); +} + +const isDevelopment = process.env.NODE_ENV === "development"; + +export default defineConfig({ + plugins: [viteSingleFile()], + build: { + sourcemap: isDevelopment ? "inline" : undefined, + cssMinify: !isDevelopment, + minify: !isDevelopment, + + rollupOptions: { + input: INPUT, + }, + outDir: "dist", + emptyOutDir: false, + }, +}); diff --git a/examples/qr-server/package.json b/examples/qr-server/package.json index dd9eb1b..b83503b 100644 --- a/examples/qr-server/package.json +++ b/examples/qr-server/package.json @@ -6,5 +6,8 @@ "start": "uv run server.py", "dev": "uv run server.py", "build": "echo 'No build step needed for Python server'" + }, + "dependencies": { + "@modelcontextprotocol/ext-apps": "^0.4.1" } } diff --git a/examples/say-server/package.json b/examples/say-server/package.json index a752ef7..a5eb23c 100644 --- a/examples/say-server/package.json +++ b/examples/say-server/package.json @@ -13,5 +13,8 @@ "start": "uv run server.py", "dev": "uv run server.py", "build": "echo 'No build step needed for Python server'" + }, + "dependencies": { + "@modelcontextprotocol/ext-apps": "^0.4.1" } } diff --git a/package-lock.json b/package-lock.json index 74b952b..f1d7e20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -97,7 +97,7 @@ } }, "examples/basic-host/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -106,8 +106,6 @@ }, "examples/basic-host/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -139,7 +137,7 @@ } }, "examples/basic-server-preact/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -148,8 +146,6 @@ }, "examples/basic-server-preact/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -184,7 +180,7 @@ } }, "examples/basic-server-react/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -193,8 +189,6 @@ }, "examples/basic-server-react/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -226,7 +220,7 @@ } }, "examples/basic-server-solid/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -235,8 +229,6 @@ }, "examples/basic-server-solid/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -268,7 +260,7 @@ } }, "examples/basic-server-svelte/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -277,8 +269,6 @@ }, "examples/basic-server-svelte/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -308,7 +298,7 @@ } }, "examples/basic-server-vanillajs/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -317,8 +307,6 @@ }, "examples/basic-server-vanillajs/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -350,7 +338,7 @@ } }, "examples/basic-server-vue/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -359,8 +347,6 @@ }, "examples/basic-server-vue/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -391,7 +377,7 @@ } }, "examples/budget-allocator-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -400,8 +386,6 @@ }, "examples/budget-allocator-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -436,7 +420,7 @@ } }, "examples/cohort-heatmap-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -445,8 +429,6 @@ }, "examples/cohort-heatmap-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -477,7 +459,7 @@ } }, "examples/customer-segmentation-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -486,8 +468,41 @@ }, "examples/customer-segmentation-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "examples/debug-server": { + "name": "@modelcontextprotocol/server-debug", + "version": "0.4.1", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/ext-apps": "^0.4.0", + "@modelcontextprotocol/sdk": "^1.24.0", + "zod": "^4.1.13" + }, + "devDependencies": { + "@types/cors": "^2.8.19", + "@types/express": "^5.0.0", + "@types/node": "^22.0.0", + "concurrently": "^9.2.1", + "cors": "^2.8.5", + "cross-env": "^10.1.0", + "express": "^5.1.0", + "typescript": "^5.9.3", + "vite": "^6.0.0", + "vite-plugin-singlefile": "^2.3.0" + } + }, + "examples/debug-server/node_modules/@types/node": { + "version": "22.19.7", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "examples/debug-server/node_modules/undici-types": { + "version": "6.21.0", "dev": true, "license": "MIT" }, @@ -519,7 +534,7 @@ } }, "examples/integration-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -528,8 +543,6 @@ }, "examples/integration-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -559,7 +572,7 @@ } }, "examples/map-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -568,8 +581,6 @@ }, "examples/map-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -600,7 +611,7 @@ } }, "examples/pdf-server/node_modules/@types/node": { - "version": "22.19.6", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -609,8 +620,6 @@ }, "examples/pdf-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -655,7 +664,7 @@ } }, "examples/scenario-modeler-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -664,8 +673,6 @@ }, "examples/scenario-modeler-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -695,7 +702,7 @@ } }, "examples/shadertoy-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -704,8 +711,6 @@ }, "examples/shadertoy-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -736,7 +741,7 @@ } }, "examples/sheet-music-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -745,8 +750,6 @@ }, "examples/sheet-music-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -778,7 +781,7 @@ } }, "examples/system-monitor-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -787,8 +790,6 @@ }, "examples/system-monitor-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -825,7 +826,7 @@ } }, "examples/threejs-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -834,8 +835,6 @@ }, "examples/threejs-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -866,7 +865,7 @@ } }, "examples/transcript-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -875,15 +874,11 @@ }, "examples/transcript-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, "examples/transcript-server/node_modules/zod": { "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -915,7 +910,7 @@ } }, "examples/video-resource-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -924,8 +919,6 @@ }, "examples/video-resource-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -957,7 +950,7 @@ } }, "examples/wiki-explorer-server/node_modules/@types/node": { - "version": "22.19.5", + "version": "22.19.7", "dev": true, "license": "MIT", "dependencies": { @@ -966,8 +959,6 @@ }, "examples/wiki-explorer-server/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -2393,20 +2384,59 @@ "license": "MIT" }, "node_modules/@modelcontextprotocol/ext-apps": { - "resolved": "", - "link": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/ext-apps/-/ext-apps-0.4.1.tgz", + "integrity": "sha512-LUw6NidwWInzWVF8OSPw/Mtdz5ES2qF+yBze2h+WRARdSbXf+agTkZLCGFtdkogI64W6mDlJnSTp/k5W+FZ84A==", + "hasInstallScript": true, + "license": "MIT", + "workspaces": [ + "examples/*" + ], + "optionalDependencies": { + "@oven/bun-darwin-aarch64": "^1.2.21", + "@oven/bun-darwin-x64": "^1.2.21", + "@oven/bun-darwin-x64-baseline": "^1.2.21", + "@oven/bun-linux-aarch64": "^1.2.21", + "@oven/bun-linux-aarch64-musl": "^1.2.21", + "@oven/bun-linux-x64": "^1.2.21", + "@oven/bun-linux-x64-baseline": "^1.2.21", + "@oven/bun-linux-x64-musl": "^1.2.21", + "@oven/bun-linux-x64-musl-baseline": "^1.2.21", + "@oven/bun-windows-x64": "^1.2.21", + "@oven/bun-windows-x64-baseline": "^1.2.21", + "@rollup/rollup-darwin-arm64": "^4.53.3", + "@rollup/rollup-darwin-x64": "^4.53.3", + "@rollup/rollup-linux-arm64-gnu": "^4.53.3", + "@rollup/rollup-linux-x64-gnu": "^4.53.3", + "@rollup/rollup-win32-arm64-msvc": "^4.53.3", + "@rollup/rollup-win32-x64-msvc": "^4.53.3" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.24.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } }, "node_modules/@modelcontextprotocol/ext-apps-basic-host": { "resolved": "examples/basic-host", "link": true }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.25.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz", - "integrity": "sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww==", + "version": "1.25.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz", + "integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.7", + "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -2475,6 +2505,10 @@ "resolved": "examples/customer-segmentation-server", "link": true }, + "node_modules/@modelcontextprotocol/server-debug": { + "resolved": "examples/debug-server", + "link": true + }, "node_modules/@modelcontextprotocol/server-map": { "resolved": "examples/map-server", "link": true @@ -3073,9 +3107,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", + "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", "cpu": [ "arm" ], @@ -3087,9 +3121,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", + "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", "cpu": [ "arm64" ], @@ -3101,9 +3135,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", + "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", "cpu": [ "arm64" ], @@ -3114,9 +3148,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", + "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", "cpu": [ "x64" ], @@ -3127,9 +3161,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", + "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", "cpu": [ "arm64" ], @@ -3141,9 +3175,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", + "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", "cpu": [ "x64" ], @@ -3155,9 +3189,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", + "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", "cpu": [ "arm" ], @@ -3169,9 +3203,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", + "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", "cpu": [ "arm" ], @@ -3183,9 +3217,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", + "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", "cpu": [ "arm64" ], @@ -3196,9 +3230,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", + "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", "cpu": [ "arm64" ], @@ -3210,9 +3244,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", + "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", "cpu": [ "loong64" ], @@ -3224,9 +3258,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", + "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", "cpu": [ "loong64" ], @@ -3238,9 +3272,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", + "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", "cpu": [ "ppc64" ], @@ -3252,9 +3286,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", + "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", "cpu": [ "ppc64" ], @@ -3266,9 +3300,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", + "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", "cpu": [ "riscv64" ], @@ -3280,9 +3314,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", + "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", "cpu": [ "riscv64" ], @@ -3294,9 +3328,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", + "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", "cpu": [ "s390x" ], @@ -3308,9 +3342,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", + "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", "cpu": [ "x64" ], @@ -3321,9 +3355,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", + "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", "cpu": [ "x64" ], @@ -3335,9 +3369,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", + "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", "cpu": [ "x64" ], @@ -3349,9 +3383,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", + "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", "cpu": [ "arm64" ], @@ -3363,9 +3397,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", + "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", "cpu": [ "arm64" ], @@ -3376,9 +3410,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", + "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", "cpu": [ "ia32" ], @@ -3390,9 +3424,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", + "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", "cpu": [ "x64" ], @@ -3404,9 +3438,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", + "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", "cpu": [ "x64" ], @@ -3682,9 +3716,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.0.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.8.tgz", - "integrity": "sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg==", + "version": "25.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", + "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", "dev": true, "license": "MIT", "peer": true, @@ -3707,9 +3741,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", - "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", + "version": "19.2.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.9.tgz", + "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==", "dev": true, "license": "MIT", "peer": true, @@ -3959,22 +3993,22 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", - "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz", + "integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.26", + "@vue/shared": "3.5.27", "entities": "^7.0.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-core/node_modules/entities": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", - "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -3984,26 +4018,26 @@ } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz", - "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz", + "integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.26", - "@vue/shared": "3.5.26" + "@vue/compiler-core": "3.5.27", + "@vue/shared": "3.5.27" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", - "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", + "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", - "@vue/compiler-core": "3.5.26", - "@vue/compiler-dom": "3.5.26", - "@vue/compiler-ssr": "3.5.26", - "@vue/shared": "3.5.26", + "@vue/compiler-core": "3.5.27", + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", @@ -4011,63 +4045,63 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz", - "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz", + "integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.26", - "@vue/shared": "3.5.26" + "@vue/compiler-dom": "3.5.27", + "@vue/shared": "3.5.27" } }, "node_modules/@vue/reactivity": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz", - "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.27.tgz", + "integrity": "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.26" + "@vue/shared": "3.5.27" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz", - "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.27.tgz", + "integrity": "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.26", - "@vue/shared": "3.5.26" + "@vue/reactivity": "3.5.27", + "@vue/shared": "3.5.27" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz", - "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.27.tgz", + "integrity": "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.26", - "@vue/runtime-core": "3.5.26", - "@vue/shared": "3.5.26", + "@vue/reactivity": "3.5.27", + "@vue/runtime-core": "3.5.27", + "@vue/shared": "3.5.27", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz", - "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.27.tgz", + "integrity": "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.26", - "@vue/shared": "3.5.26" + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27" }, "peerDependencies": { - "vue": "3.5.26" + "vue": "3.5.27" } }, "node_modules/@vue/shared": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz", - "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz", + "integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==", "license": "MIT" }, "node_modules/@webgpu/types": { @@ -4334,9 +4368,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.14", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "version": "2.9.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz", + "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4515,9 +4549,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "version": "1.0.30001765", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", + "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", "dev": true, "funding": [ { @@ -4917,9 +4951,9 @@ } }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -4927,6 +4961,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cross-env": { @@ -5077,9 +5115,9 @@ } }, "node_modules/d3-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.1.tgz", - "integrity": "sha512-ryitBnaRbXQtgZ/gU50GSn6jQRwinSCQclpakXymvLd8ytTgE5bmSfgYcUxD7XYL34qHhFDyVk71qqKsfSyvmA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", "dev": true, "license": "ISC", "engines": { @@ -5385,9 +5423,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.277", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.277.tgz", + "integrity": "sha512-wKXFZw4erWmmOz5N/grBoJ2XrNJGDFMu2+W5ACHza5rHtvsqrK4gb6rnLC7XxKB9WlJ+RmyQatuEXmtm86xbnw==", "dev": true, "license": "ISC" }, @@ -5572,9 +5610,9 @@ "license": "MIT" }, "node_modules/esrap": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz", - "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.2.tgz", + "integrity": "sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -5596,9 +5634,9 @@ } }, "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "dev": true, "license": "MIT" }, @@ -5714,6 +5752,24 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", @@ -6034,16 +6090,6 @@ "he": "bin/he" } }, - "node_modules/hono": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", - "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/html-entities": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", @@ -6052,9 +6098,9 @@ "license": "MIT" }, "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -6066,14 +6112,14 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.2.1", - "entities": "^6.0.0" + "domutils": "^3.2.2", + "entities": "^7.0.1" } }, "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -6521,9 +6567,9 @@ "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "dev": true, "license": "MIT" }, @@ -7199,9 +7245,9 @@ } }, "node_modules/prettier": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", - "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", "bin": { @@ -7382,9 +7428,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", + "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", "dev": true, "license": "MIT", "peer": true, @@ -7399,31 +7445,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", + "@rollup/rollup-android-arm-eabi": "4.56.0", + "@rollup/rollup-android-arm64": "4.56.0", + "@rollup/rollup-darwin-arm64": "4.56.0", + "@rollup/rollup-darwin-x64": "4.56.0", + "@rollup/rollup-freebsd-arm64": "4.56.0", + "@rollup/rollup-freebsd-x64": "4.56.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", + "@rollup/rollup-linux-arm-musleabihf": "4.56.0", + "@rollup/rollup-linux-arm64-gnu": "4.56.0", + "@rollup/rollup-linux-arm64-musl": "4.56.0", + "@rollup/rollup-linux-loong64-gnu": "4.56.0", + "@rollup/rollup-linux-loong64-musl": "4.56.0", + "@rollup/rollup-linux-ppc64-gnu": "4.56.0", + "@rollup/rollup-linux-ppc64-musl": "4.56.0", + "@rollup/rollup-linux-riscv64-gnu": "4.56.0", + "@rollup/rollup-linux-riscv64-musl": "4.56.0", + "@rollup/rollup-linux-s390x-gnu": "4.56.0", + "@rollup/rollup-linux-x64-gnu": "4.56.0", + "@rollup/rollup-linux-x64-musl": "4.56.0", + "@rollup/rollup-openbsd-x64": "4.56.0", + "@rollup/rollup-openharmony-arm64": "4.56.0", + "@rollup/rollup-win32-arm64-msvc": "4.56.0", + "@rollup/rollup-win32-ia32-msvc": "4.56.0", + "@rollup/rollup-win32-x64-gnu": "4.56.0", + "@rollup/rollup-win32-x64-msvc": "4.56.0", "fsevents": "~2.3.2" } }, @@ -7975,9 +8021,9 @@ } }, "node_modules/svelte": { - "version": "5.46.4", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.46.4.tgz", - "integrity": "sha512-VJwdXrmv9L8L7ZasJeWcCjoIuMRVbhuxbss0fpVnR8yorMmjNDwcjIH08vS6wmSzzzgAG5CADQ1JuXPS2nwt9w==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.0.tgz", + "integrity": "sha512-+NUe82VoFP1RQViZI/esojx70eazGF4u0O/9ucqZ4rPcOZD+n5EVp17uYsqwdzjUjZyTpGKunHbDziW6AIAVkQ==", "license": "MIT", "peer": true, "dependencies": { @@ -8002,9 +8048,9 @@ } }, "node_modules/systeminformation": { - "version": "5.30.3", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.3.tgz", - "integrity": "sha512-NgHJUpA+y7j4asLQa9jgBt+Eb2piyQIXQ+YjOyd2K0cHNwbNJ6I06F5afOqOiaCuV/wrEyGrb0olg4aFLlJD+A==", + "version": "5.30.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.5.tgz", + "integrity": "sha512-DpWmpCckhwR3hG+6udb6/aQB7PpiqVnvSljrjbKxNSvTRsGsg7NVE3/vouoYf96xgwMxXFKcS4Ux+cnkFwYM7A==", "license": "MIT", "os": [ "darwin", @@ -8028,214 +8074,214 @@ } }, "node_modules/text-camel-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.9.tgz", - "integrity": "sha512-wKYs9SgRxYizJE1mneR7BbLNlGw2IYzJAS8XwkWIry0CTbO1gvvPkFsx5Z1/hr+VqUaBqx9q3yKd30HpZLdMsQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.10.tgz", + "integrity": "sha512-KNrWeZzQT+gh73V1LnmgTkjK7V+tMRjLCc6VrGwkqbiRdnGVIWBUgIvVnvnaVCxIvZ/2Ke8DCmgPirlQcCqD3Q==", "dev": true, "license": "MIT", "dependencies": { - "text-pascal-case": "1.2.9" + "text-pascal-case": "1.2.10" } }, "node_modules/text-capital-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.9.tgz", - "integrity": "sha512-X5zV8U8pxtq2xS2t46lgAWqZdDbgWMKq03MQSNwY2CJdQCsdTNh144E2Q/q9wBxWzSBUXn+jRc9kF+Gs8/pGhA==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.10.tgz", + "integrity": "sha512-yvViUJKSSQcRO58je224bhPHg/Hij9MEY43zuKShtFzrPwW/fOAarUJ5UkTMSB81AOO1m8q+JiFdxMF4etKZbA==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9", - "text-upper-case-first": "1.2.9" + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" } }, "node_modules/text-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.9.tgz", - "integrity": "sha512-zZVdA8rMcjx9zhekdUuOPZShc25UTV7W8/ddKbgbPtfCEvIiToPtWiSd2lXLSuiGMovNhJ4+Tw49xll9o9ts+Q==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.10.tgz", + "integrity": "sha512-5bY3Ks/u7OJ5YO69iyXrG5Xf2wUZeyko7U78nPUnYoSeuNeAfA5uAix5hTspfkl6smm3yCBObrex+kFvzeIcJg==", "dev": true, "license": "MIT", "dependencies": { - "text-camel-case": "1.2.9", - "text-capital-case": "1.2.9", - "text-constant-case": "1.2.9", - "text-dot-case": "1.2.9", - "text-header-case": "1.2.9", - "text-is-lower-case": "1.2.9", - "text-is-upper-case": "1.2.9", - "text-kebab-case": "1.2.9", - "text-lower-case": "1.2.9", - "text-lower-case-first": "1.2.9", - "text-no-case": "1.2.9", - "text-param-case": "1.2.9", - "text-pascal-case": "1.2.9", - "text-path-case": "1.2.9", - "text-sentence-case": "1.2.9", - "text-snake-case": "1.2.9", - "text-swap-case": "1.2.9", - "text-title-case": "1.2.9", - "text-upper-case": "1.2.9", - "text-upper-case-first": "1.2.9" + "text-camel-case": "1.2.10", + "text-capital-case": "1.2.10", + "text-constant-case": "1.2.10", + "text-dot-case": "1.2.10", + "text-header-case": "1.2.10", + "text-is-lower-case": "1.2.10", + "text-is-upper-case": "1.2.10", + "text-kebab-case": "1.2.10", + "text-lower-case": "1.2.10", + "text-lower-case-first": "1.2.10", + "text-no-case": "1.2.10", + "text-param-case": "1.2.10", + "text-pascal-case": "1.2.10", + "text-path-case": "1.2.10", + "text-sentence-case": "1.2.10", + "text-snake-case": "1.2.10", + "text-swap-case": "1.2.10", + "text-title-case": "1.2.10", + "text-upper-case": "1.2.10", + "text-upper-case-first": "1.2.10" } }, "node_modules/text-constant-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.9.tgz", - "integrity": "sha512-Vosm6nC7Gag+JFakJHwqS9AXRNgl07j5KZ7srU9cYuKRzYwrxzeJ4RpEogRBNHw7CfmOm0j5FGEznblWtu7pIw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.10.tgz", + "integrity": "sha512-/OfU798O2wrwKN9kQf71WhJeAlklGnbby0Tupp+Ez9NXymW+6oF9LWDRTkN+OreTmHucdvp4WQd6O5Rah5zj8A==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9", - "text-upper-case": "1.2.9" + "text-no-case": "1.2.10", + "text-upper-case": "1.2.10" } }, "node_modules/text-dot-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.9.tgz", - "integrity": "sha512-N83hsnvGdSO9q9AfNSB9Cy1LFDNN2MCx53LcxtaPoDWPUTk47fv0JlvIY1tgY0wyzCiThF03kVj3jworvAOScA==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.10.tgz", + "integrity": "sha512-vf4xguy5y6e39RlDZeWZFMDf2mNkR23VTSVb9e68dUSpfJscG9/1YWWpW3n8TinzQxBZlsn5sT5olL33MvvQXw==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9" + "text-no-case": "1.2.10" } }, "node_modules/text-header-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.9.tgz", - "integrity": "sha512-TqryEKcYisQAfWLbtT3xPnZlMZ/mySO1uS+LUg+B0eNuqgETrSzVpXIUj5E6Zf/EyJHgpZf4VndbAXtOMJuT4w==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.10.tgz", + "integrity": "sha512-sVb1NY9bwxtu+Z7CVyWbr+I0AkWtF0kEHL/Zz5V2u/WdkjK5tKBwl5nXf0NGy9da4ZUYTBb+TmQpOIqihzvFMQ==", "dev": true, "license": "MIT", "dependencies": { - "text-capital-case": "1.2.9" + "text-capital-case": "1.2.10" } }, "node_modules/text-is-lower-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.9.tgz", - "integrity": "sha512-cEurrWSnYVYqL8FSwl5cK4mdfqF7qNDCcKJgXI3NnfTesiB8umxAhdlQoErrRYI1xEvYr2WN0MI333EehUhQjg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.10.tgz", + "integrity": "sha512-dMTeTgrdWWfYf3fKxvjMkDPuXWv96cWbd1Uym6Zjv9H855S1uHxjkFsGbTYJ2tEK0NvAylRySTQlI6axlcMc4w==", "dev": true, "license": "MIT" }, "node_modules/text-is-upper-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.9.tgz", - "integrity": "sha512-HxsWr3VCsXXiLlhD0c+Ey+mS2lOTCiSJbkepjaXNHl2bp33KiscQaiG0qLwQmmpZQm4SJCg2s9FkndxS0RNDLQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.10.tgz", + "integrity": "sha512-PGD/cXoXECGAY1HVZxDdmpJUW2ZUAKQ6DTamDfCHC9fc/z4epOz0pB/ThBnjJA3fz+d2ApkMjAfZDjuZFcodzg==", "dev": true, "license": "MIT" }, "node_modules/text-kebab-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.9.tgz", - "integrity": "sha512-nOUyNR5Ej2B9D/wyyXfwUEv26+pQuOb1pEX+ojE37mCIWo8QeOxw5y6nxuqDmG7NrEPzbO6265UMV+EICH13Cw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.10.tgz", + "integrity": "sha512-3XZJAApx5JQpUO7eXo7GQ2TyRcGw3OVbqxz6QJb2h+N8PbLLbz3zJVeXdGrhTkoUIbkSZ6PmHx6LRDaHXTdMcA==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9" + "text-no-case": "1.2.10" } }, "node_modules/text-lower-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.9.tgz", - "integrity": "sha512-53AOnDrhPpiAUQkgY1SHleKUXp/u7GsqRX13NcCREZscmtjLLJ099uxMRjkK7q2KwHkFYVPl9ytkQlTkTQLS0w==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.10.tgz", + "integrity": "sha512-c9j5pIAN3ObAp1+4R7970e1bgtahTRF/5ZQdX2aJBuBngYTYZZIck0NwFXUKk5BnYpLGsre5KFHvpqvf4IYKgg==", "dev": true, "license": "MIT" }, "node_modules/text-lower-case-first": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.9.tgz", - "integrity": "sha512-iiphHTV7PVH0MljrEQUA9iBE7jfDpXoi4RQju3WzZU3BRVbS6540cNZgxR19hWa0z6z/7cJTH0Ls9LPBaiUfKg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.10.tgz", + "integrity": "sha512-Oro84jZPDLD9alfdZWmtFHYTvCaaSz2o4thPtjMsK4GAkTyVg9juYXWj0y0YFyjLYGH69muWsBe4/MR5S7iolw==", "dev": true, "license": "MIT" }, "node_modules/text-no-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.9.tgz", - "integrity": "sha512-IcCt328KaapimSrytP4ThfC8URmHZb2DgOqCL9BYvGjpxY2lDiqCkIQk9sClZtwcELs2gTnq83a7jNc573FTLA==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.10.tgz", + "integrity": "sha512-4/m79pzQrywrwEG5lCULY1lQvFY+EKjhH9xSMT6caPK5plqzm9Y7rXyv+UXPd3s9qH6QODZnvsAYWW3M0JgxRA==", "dev": true, "license": "MIT", "dependencies": { - "text-lower-case": "1.2.9" + "text-lower-case": "1.2.10" } }, "node_modules/text-param-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.9.tgz", - "integrity": "sha512-nR/Ju9amY3aQS1en2CUCgqN/ZiZIVdDyjlJ3xX5J92ChBevGuA4o9K10fh3JGMkbzK97Vcb+bWQJ4Q+Svz+GyQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.10.tgz", + "integrity": "sha512-hkavcLsRRzZcGryPAshct1AwIOMj/FexYjMaLpGZCYYBn1lcZEeyMzJZPSckzkOYpq35LYSQr3xZto9XU5OAsw==", "dev": true, "license": "MIT", "dependencies": { - "text-dot-case": "1.2.9" + "text-dot-case": "1.2.10" } }, "node_modules/text-pascal-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.9.tgz", - "integrity": "sha512-o6ZxMGjWDTUW54pcghpXes+C2PqbYRMdU5mHrIhueb6z6nq1NueiIOeCUdrSjN/3wXfhCmnFjK7/d9aRGZNqSg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.10.tgz", + "integrity": "sha512-/kynZD8vTYOmm/RECjIDaz3qYEUZc/N/bnC79XuAFxwXjdNVjj/jGovKJLRzqsYK/39N22XpGcVmGg7yIrbk6w==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9" + "text-no-case": "1.2.10" } }, "node_modules/text-path-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.9.tgz", - "integrity": "sha512-s8cJ6r5TkJp5ticXMgtxd7f12odEN4d1CfX5u4aoz6jcUtBR2lDqzIhVimkqWFMJ4UKPSrmilUha8Xc2BPi+ow==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.10.tgz", + "integrity": "sha512-vbKdRCaVEeOaW6sm24QP9NbH7TS9S4ZQ3u19H8eylDox7m2HtFwYIBjAPv+v3z4I/+VjrMy9LB54lNP1uEqRHw==", "dev": true, "license": "MIT", "dependencies": { - "text-dot-case": "1.2.9" + "text-dot-case": "1.2.10" } }, "node_modules/text-sentence-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.9.tgz", - "integrity": "sha512-/G/Yi5kZfUa1edFRV4O3lGZAkbDZTFvlwW8CYfH7szkEGe2k2MYEYbOyAkGRVQEGV6V6JiuUAaP3VS9c1tB6nQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.10.tgz", + "integrity": "sha512-NO4MRlbfxFhl9QgQLuCL4xHmvE7PUWHVPWsZxQ5nzRtDjXOUllWvtsvl8CP5tBEvBmzg0kwfflxfhRtr5vBQGg==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9", - "text-upper-case-first": "1.2.9" + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" } }, "node_modules/text-snake-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.9.tgz", - "integrity": "sha512-+ZrqK19ynF/TLQZ7ynqVrL2Dy04uu9syYZwsm8PhzUdsY3XrwPy6QiRqhIEFqhyWbShPcfyfmheer5UEQqFxlw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.10.tgz", + "integrity": "sha512-6ttMZ+B9jkHKun908HYr4xSvEtlbfJJ4MvpQ06JEKRGhwjMI0x8t2Wywp+MEzN6142O6E/zKhra18KyBL6cvXA==", "dev": true, "license": "MIT", "dependencies": { - "text-dot-case": "1.2.9" + "text-dot-case": "1.2.10" } }, "node_modules/text-swap-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.9.tgz", - "integrity": "sha512-g5fp12ldktYKK9wdHRMvvtSCQrZYNv/D+ZGLumDsvAY4q9T5bCMO2IWMkIP1F5gVQrysdHH6Xv877P/pjUq1iw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.10.tgz", + "integrity": "sha512-vO3jwInIk0N77oEFakYZ2Hn/llTmRwf2c3RvkX/LfvmLWVp+3QcIc6bwUEtbqGQ5Xh2okjFhYrfkHZstVc3N4Q==", "dev": true, "license": "MIT" }, "node_modules/text-title-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.9.tgz", - "integrity": "sha512-RAtC9cdmPp41ns5/HXZBsaQg71BsHT7uZpj2ojTtuFa8o2dNuRYYOrSmy5YdLRIAJQ6WK5hQVpV3jHuq7a+4Tw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.10.tgz", + "integrity": "sha512-bqA+WWexUMWu9A3fdNar+3GXXW+c5xOvMyuK5hOx/w0AlqhyQptyCrMFjGB8Fd9dxbryBNmJ+5rWtC1OBDxlaA==", "dev": true, "license": "MIT", "dependencies": { - "text-no-case": "1.2.9", - "text-upper-case-first": "1.2.9" + "text-no-case": "1.2.10", + "text-upper-case-first": "1.2.10" } }, "node_modules/text-upper-case": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.9.tgz", - "integrity": "sha512-K/0DNT7a4z8eah2spARtoJllTZyrNTo6Uc0ujhN/96Ir9uJ/slpahfs13y46H9osL3daaLl3O7iXOkW4xtX6bg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.10.tgz", + "integrity": "sha512-L1AtZ8R+jtSMTq0Ffma9R4Rzbrc3iuYW89BmWFH41AwnDfRmEBlBOllm1ZivRLQ/6pEu2p+3XKBHx9fsMl2CWg==", "dev": true, "license": "MIT" }, "node_modules/text-upper-case-first": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.9.tgz", - "integrity": "sha512-wEDD1B6XqJmEV+xEnBJd+2sBCHZ+7fvA/8Rv/o8+dAsp05YWjYP/kjB8sPH6zqzW0s6jtehIg4IlcKjcYxk2CQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.10.tgz", + "integrity": "sha512-VXs7j7BbpKwvolDh5fwpYRmMrUHGkxbY8E90fhBzKUoKfadvWmPT/jFieoZ4UPLzr208pXvQEFbb2zO9Qzs9Fg==", "dev": true, "license": "MIT" }, @@ -8283,24 +8329,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", @@ -9068,7 +9096,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "peer": true, "bin": { @@ -9094,9 +9122,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.2.tgz", - "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.0.tgz", + "integrity": "sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -9317,24 +9345,6 @@ "vite": "5.x || 6.x || 7.x" } }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", @@ -9456,17 +9466,17 @@ } }, "node_modules/vue": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", - "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", + "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.26", - "@vue/compiler-sfc": "3.5.26", - "@vue/runtime-dom": "3.5.26", - "@vue/server-renderer": "3.5.26", - "@vue/shared": "3.5.26" + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-sfc": "3.5.27", + "@vue/runtime-dom": "3.5.27", + "@vue/server-renderer": "3.5.27", + "@vue/shared": "3.5.27" }, "peerDependencies": { "typescript": "*" @@ -9680,9 +9690,9 @@ "license": "MIT" }, "node_modules/zod": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "peer": true, "funding": { diff --git a/tests/e2e/generate-grid-screenshots.spec.ts b/tests/e2e/generate-grid-screenshots.spec.ts index 1bc639c..f36bf67 100644 --- a/tests/e2e/generate-grid-screenshots.spec.ts +++ b/tests/e2e/generate-grid-screenshots.spec.ts @@ -55,6 +55,7 @@ const ALL_SERVERS = [ name: "Customer Segmentation Server", dir: "customer-segmentation-server", }, + { key: "debug-server", name: "Debug MCP App Server", dir: "debug-server" }, { key: "map-server", name: "Map Server", dir: "map-server" }, { key: "pdf-server", name: "PDF Server", dir: "pdf-server" }, { key: "qr-server", name: "QR Code Server", dir: "qr-server" }, diff --git a/tests/e2e/servers.spec.ts b/tests/e2e/servers.spec.ts index 323f266..7bdb2a1 100644 --- a/tests/e2e/servers.spec.ts +++ b/tests/e2e/servers.spec.ts @@ -16,6 +16,7 @@ const DYNAMIC_MASKS: Record = { "basic-vue": ["#server-time"], // Server time display "cohort-heatmap": ['[class*="heatmapWrapper"]'], // Heatmap grid (random data) "customer-segmentation": [".chart-container"], // Scatter plot (random data) + "debug-server": ["#event-log", "#callback-table-body"], // Event log and callback counts (dynamic) "say-server": [".playBtn", ".playOverlayBtn"], // Play buttons may have different states shadertoy: ["#canvas"], // WebGL shader canvas (animated) "system-monitor": [ @@ -96,6 +97,7 @@ const ALL_SERVERS = [ name: "Customer Segmentation Server", dir: "customer-segmentation-server", }, + { key: "debug-server", name: "Debug MCP App Server", dir: "debug-server" }, { key: "map-server", name: "Map Server", dir: "map-server" }, { key: "pdf-server", name: "PDF Server", dir: "pdf-server" }, { key: "qr-server", name: "QR Code Server", dir: "qr-server" }, diff --git a/tests/e2e/servers.spec.ts-snapshots/debug-server.png b/tests/e2e/servers.spec.ts-snapshots/debug-server.png new file mode 100644 index 0000000..c1fc4ad Binary files /dev/null and b/tests/e2e/servers.spec.ts-snapshots/debug-server.png differ