{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "mcp-server-registry-manager",
  "title": "Mcp Server Registry Manager",
  "type": "registry:page",
  "files": [
    {
      "path": "packages/registry-react/blocks/mcp-server-registry-manager/McpServerRegistryManager.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  Activity,\n  Boxes,\n  Braces,\n  Check,\n  CheckCircle2,\n  Code2,\n  Copy,\n  FileCode,\n  Link2,\n  MoreHorizontal,\n  Plus,\n  Radio,\n  RefreshCw,\n  Search,\n  Server,\n  ShieldCheck,\n  Terminal,\n  Trash2,\n  Wrench,\n  X,\n  Zap,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\nimport { McpToolInspectorDrawer } from './McpToolInspectorDrawer'\n\nexport type TransportType = 'stdio' | 'sse'\nexport type ServerStatus = 'healthy' | 'reconnecting' | 'degraded'\n\nexport interface ToolParam {\n  name: string\n  type: 'string' | 'number' | 'boolean' | 'object' | 'array'\n  required: boolean\n  description: string\n  default?: string\n  enum?: string[]\n}\n\nexport interface ToolSchema {\n  name: string\n  displayName: string\n  description: string\n  category: 'documentation' | 'database' | 'version-control' | 'deployment' | 'web-search' | 'observability'\n  parameters: ToolParam[]\n  sampleRpcRequest: {\n    jsonrpc: '2.0'\n    id: string\n    method: 'tools/call'\n    params: {\n      name: string\n      arguments: Record<string, any>\n    }\n  }\n  sampleRpcResponse: {\n    jsonrpc: '2.0'\n    id: string\n    result: {\n      content: Array<{\n        type: 'text' | 'resource' | 'image'\n        text?: string\n        resource?: any\n      }>\n      isError: boolean\n    }\n  }\n}\n\nexport interface ResourceTemplate {\n  uriTemplate: string\n  name: string\n  description: string\n  mimeType: string\n}\n\nexport interface McpServer {\n  id: string\n  name: string\n  scope: string\n  version: string\n  transport: TransportType\n  commandOrUrl: string\n  status: ServerStatus\n  uptime: string\n  latencyMs: number\n  callsToday: number\n  description: string\n  envVars: string[]\n  resourceTemplates: ResourceTemplate[]\n  tools: ToolSchema[]\n}\n\nexport interface McpServerRegistryManagerProps {\n  className?: string\n  initialSearch?: string\n  initialTransportFilter?: 'all' | 'stdio' | 'sse'\n  initialStatusFilter?: 'all' | 'healthy' | 'reconnecting'\n  initialSelectedToolName?: string\n  initialDrawerOpen?: boolean\n  initialInstallDialogOpen?: boolean\n  initialHandshakeAlert?: boolean\n  initialServers?: McpServer[]\n}\n\nconst defaultServers: McpServer[] = [\n  {\n    id: 'server-ctx-1',\n    name: 'mcp/context7-docs',\n    scope: '@context7/mcp-server',\n    version: 'v1.4.2',\n    transport: 'stdio',\n    commandOrUrl: 'npx -y @context7/mcp-server',\n    status: 'healthy',\n    uptime: '99.98%',\n    latencyMs: 18,\n    callsToday: 4120,\n    description: 'Context-aware documentation retriever and code snippet indexer for public libraries and frameworks.',\n    envVars: ['CONTEXT7_API_KEY=c7_live_***', 'CACHE_TTL=3600'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'docs://{library}/{version}',\n        name: 'Library Documentation AST',\n        description: 'Direct access to indexed AST documentation, type exports, and code snippets',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'cheatsheets://{framework}/api-reference',\n        name: 'Framework Cheatsheet',\n        description: 'High-density API method cheat sheets and migration summaries',\n        mimeType: 'text/markdown',\n      },\n    ],\n    tools: [\n      {\n        name: 'query_docs',\n        displayName: 'Query Library Docs',\n        description:\n          'Retrieves up-to-date documentation and code examples from Context7 for any programming library or framework.',\n        category: 'documentation',\n        parameters: [\n          {\n            name: 'libraryId',\n            type: 'string',\n            required: true,\n            description: 'Exact Context7-compatible library ID (e.g. /tailwindlabs/tailwindcss or /unovue/reka-ui).',\n          },\n          {\n            name: 'query',\n            type: 'string',\n            required: true,\n            description: 'What to look up in the library documentation, scoped to a single concept.',\n          },\n          {\n            name: 'limit',\n            type: 'number',\n            required: false,\n            default: '5',\n            description: 'Maximum number of relevant code snippets to return (1-20).',\n          },\n          {\n            name: 'includeSnippets',\n            type: 'boolean',\n            required: false,\n            default: 'true',\n            description: 'Whether to include verified code snippet examples in markdown format.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-ctx-001',\n          method: 'tools/call',\n          params: {\n            name: 'query_docs',\n            arguments: {\n              libraryId: '/tailwindlabs/tailwindcss',\n              query: 'CSS variables and OKLCH color palettes v4',\n              limit: 3,\n              includeSnippets: true,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-ctx-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: 'Tailwind CSS v4 introduces native CSS-first theme configuration using `@theme` and OKLCH color functions without javascript config files.',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'resolve_library_id',\n        displayName: 'Resolve Library ID',\n        description:\n          'Resolves a package or product name to a Context7-compatible library ID and returns matching ranked libraries.',\n        category: 'documentation',\n        parameters: [\n          {\n            name: 'libraryName',\n            type: 'string',\n            required: true,\n            description: 'Library name to search for (e.g. Next.js, Reka UI, Lucide).',\n          },\n          {\n            name: 'ecosystem',\n            type: 'string',\n            required: false,\n            default: 'npm',\n            enum: ['npm', 'pypi', 'crates', 'go', 'gem'],\n            description: 'Package registry ecosystem to prioritize during identifier resolution.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-ctx-002',\n          method: 'tools/call',\n          params: {\n            name: 'resolve_library_id',\n            arguments: {\n              libraryName: 'reka-ui',\n              ecosystem: 'npm',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-ctx-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"libraryId\":\"/unovue/reka-ui\",\"name\":\"Reka UI\",\"description\":\"Headless UI primitives for Vue 3.5\",\"reputation\":\"High\",\"benchmarkScore\":99}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n  {\n    id: 'server-pg-2',\n    name: 'mcp/postgres-inspector',\n    scope: '@modelcontextprotocol/server-postgres',\n    version: 'v0.9.1',\n    transport: 'stdio',\n    commandOrUrl: 'npx -y @modelcontextprotocol/server-postgres postgresql://app_user:***@db.internal:5432/prod_main',\n    status: 'healthy',\n    uptime: '99.95%',\n    latencyMs: 24,\n    callsToday: 3450,\n    description:\n      'Direct PostgreSQL read-only query execution, EXPLAIN execution plan inspector, and live schema reflection.',\n    envVars: ['PGSSLMODE=require', 'MAX_CONNECTIONS=10'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'postgres://{schema}/{table}',\n        name: 'Table Schema Definition',\n        description: 'PostgreSQL table column constraints, foreign keys, row count estimations, and B-Tree indexes',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'postgres://metrics/slow-queries',\n        name: 'PgStatStatements Log Buffer',\n        description: 'Aggregated query execution statistics and cache hit ratios',\n        mimeType: 'application/json',\n      },\n    ],\n    tools: [\n      {\n        name: 'execute_sql',\n        displayName: 'Execute Read-Only SQL',\n        description:\n          'Executes read-only SQL queries against Postgres connection with safe execution timeout safeguards.',\n        category: 'database',\n        parameters: [\n          {\n            name: 'query',\n            type: 'string',\n            required: true,\n            description: 'SQL statement (SELECT only) to execute on the cluster.',\n          },\n          {\n            name: 'readOnly',\n            type: 'boolean',\n            required: false,\n            default: 'true',\n            description: 'Enforces transaction read-only flag before executing SQL.',\n          },\n          {\n            name: 'timeoutMs',\n            type: 'number',\n            required: false,\n            default: '5000',\n            description: 'Statement cancellation timeout in milliseconds.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-pg-001',\n          method: 'tools/call',\n          params: {\n            name: 'execute_sql',\n            arguments: {\n              query: 'SELECT id, email, role, created_at FROM public.users WHERE is_active = true LIMIT 5;',\n              readOnly: true,\n              timeoutMs: 5000,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-pg-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"rows\":[{\"id\":\"usr_8492\",\"email\":\"alex@example.com\",\"role\":\"admin\",\"created_at\":\"2026-02-14T08:30:00Z\"}],\"rowCount\":1,\"durationMs\":14.2}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'explain_query',\n        displayName: 'Explain Query Plan',\n        description: 'Runs EXPLAIN ANALYZE on query plans to detect slow sequential scans and missing indexes.',\n        category: 'database',\n        parameters: [\n          {\n            name: 'query',\n            type: 'string',\n            required: true,\n            description: 'SQL query to analyze execution graph and node timings.',\n          },\n          {\n            name: 'analyze',\n            type: 'boolean',\n            required: false,\n            default: 'true',\n            description: 'Execute statement to measure actual wall-clock row counts and buffer usage.',\n          },\n          {\n            name: 'format',\n            type: 'string',\n            required: false,\n            default: 'json',\n            enum: ['json', 'text', 'yaml'],\n            description: 'Postgres execution plan output serialization format.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-pg-002',\n          method: 'tools/call',\n          params: {\n            name: 'explain_query',\n            arguments: {\n              query: 'SELECT * FROM orders WHERE user_id = $1 ORDER BY created_at DESC;',\n              analyze: true,\n              format: 'json',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-pg-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"Plan\":{\"Node Type\":\"Index Scan\",\"Index Name\":\"idx_orders_user_id\",\"Startup Cost\":0.42,\"Total Cost\":8.44,\"Plan Rows\":1,\"Actual Rows\":1,\"Actual Total Time\":0.114}}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'inspect_schema',\n        displayName: 'Inspect Schema Meta',\n        description: 'Returns table column definitions, constraints, foreign keys, and indexes for a database schema.',\n        category: 'database',\n        parameters: [\n          {\n            name: 'schema',\n            type: 'string',\n            required: false,\n            default: 'public',\n            description: 'Target namespace schema name (e.g. public, auth, billing).',\n          },\n          {\n            name: 'includeForeignKeys',\n            type: 'boolean',\n            required: false,\n            default: 'true',\n            description: 'Include relation cardinality graphs and ON DELETE cascade actions.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-pg-003',\n          method: 'tools/call',\n          params: {\n            name: 'inspect_schema',\n            arguments: {\n              schema: 'public',\n              includeForeignKeys: true,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-pg-003',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"schema\":\"public\",\"tablesCount\":18,\"tables\":[\"users\",\"teams\",\"orders\",\"invoices\",\"audit_logs\"]}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n  {\n    id: 'server-gh-3',\n    name: 'mcp/github-tools',\n    scope: '@modelcontextprotocol/server-github',\n    version: 'v2.1.0',\n    transport: 'stdio',\n    commandOrUrl: 'npx -y @modelcontextprotocol/server-github',\n    status: 'healthy',\n    uptime: '99.91%',\n    latencyMs: 92,\n    callsToday: 2890,\n    description:\n      'GitHub REST & GraphQL API bindings for pull request management, diff inspection, and GitHub Actions CI triggers.',\n    envVars: ['GITHUB_PERSONAL_ACCESS_TOKEN=ghp_live_***'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'github://repos/{owner}/{repo}/pulls/{number}',\n        name: 'Pull Request Snapshot',\n        description: 'Structured pull request metadata, commits, CI checks, and review discussions',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'github://repos/{owner}/{repo}/actions/{runId}',\n        name: 'CI Workflow Run Logs',\n        description: 'GitHub Actions build step outputs and failure diagnostics',\n        mimeType: 'text/plain',\n      },\n    ],\n    tools: [\n      {\n        name: 'create_pr',\n        displayName: 'Create Pull Request',\n        description: 'Creates a GitHub pull request with title, description, branch target, and reviewer tags.',\n        category: 'version-control',\n        parameters: [\n          { name: 'owner', type: 'string', required: true, description: 'GitHub account or organization name.' },\n          { name: 'repo', type: 'string', required: true, description: 'Repository name.' },\n          { name: 'title', type: 'string', required: true, description: 'Pull request header title.' },\n          { name: 'head', type: 'string', required: true, description: 'Source branch containing commits.' },\n          { name: 'base', type: 'string', required: true, description: 'Target branch (e.g. main).' },\n          { name: 'draft', type: 'boolean', required: false, default: 'false', description: 'Create in draft mode.' },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-gh-001',\n          method: 'tools/call',\n          params: {\n            name: 'create_pr',\n            arguments: {\n              owner: 'uday-a',\n              repo: 'uipkge',\n              title: 'feat(mcp): add mcp-server-registry-manager block',\n              head: 'feat/mcp-manager',\n              base: 'main',\n              draft: false,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-gh-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"number\":142,\"url\":\"https://github.com/uday-a/uipkge/pull/142\",\"status\":\"open\",\"mergeable\":true}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'review_diff',\n        displayName: 'Review Diff',\n        description: 'Fetches and analyzes pull request unified diffs against target base branch.',\n        category: 'version-control',\n        parameters: [\n          { name: 'owner', type: 'string', required: true, description: 'Repository owner.' },\n          { name: 'repo', type: 'string', required: true, description: 'Repository name.' },\n          { name: 'pullNumber', type: 'number', required: true, description: 'GitHub pull request number.' },\n          {\n            name: 'contextLines',\n            type: 'number',\n            required: false,\n            default: '3',\n            description: 'Number of surrounding context lines to include.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-gh-002',\n          method: 'tools/call',\n          params: {\n            name: 'review_diff',\n            arguments: {\n              owner: 'uday-a',\n              repo: 'uipkge',\n              pullNumber: 142,\n              contextLines: 3,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-gh-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: 'diff --git a/components/blocks/McpServerRegistryManager.tsx b/components/blocks/McpServerRegistryManager.tsx\\n+export function McpServerRegistryManager() { return <div>...</div> }',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'merge_pr',\n        displayName: 'Merge Pull Request',\n        description: 'Performs squash-merge or merge commit with branch auto-deletion.',\n        category: 'version-control',\n        parameters: [\n          { name: 'owner', type: 'string', required: true, description: 'Repository owner.' },\n          { name: 'repo', type: 'string', required: true, description: 'Repository name.' },\n          { name: 'pullNumber', type: 'number', required: true, description: 'Pull request number.' },\n          {\n            name: 'mergeMethod',\n            type: 'string',\n            required: false,\n            default: 'squash',\n            enum: ['squash', 'merge', 'rebase'],\n            description: 'Git merge strategy to apply.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-gh-003',\n          method: 'tools/call',\n          params: {\n            name: 'merge_pr',\n            arguments: {\n              owner: 'uday-a',\n              repo: 'uipkge',\n              pullNumber: 142,\n              mergeMethod: 'squash',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-gh-003',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"sha\":\"8a7c2b3d...\",\"merged\":true,\"message\":\"Pull Request successfully merged and closed\"}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'get_workflow_runs',\n        displayName: 'Get Workflow Runs',\n        description: 'Lists GitHub Actions CI workflow run statuses and failure logs.',\n        category: 'version-control',\n        parameters: [\n          { name: 'owner', type: 'string', required: true, description: 'Repository owner.' },\n          { name: 'repo', type: 'string', required: true, description: 'Repository name.' },\n          {\n            name: 'status',\n            type: 'string',\n            required: false,\n            default: 'completed',\n            enum: ['completed', 'in_progress', 'queued', 'failure'],\n            description: 'Filter CI runs by lifecycle status.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-gh-004',\n          method: 'tools/call',\n          params: {\n            name: 'get_workflow_runs',\n            arguments: {\n              owner: 'uday-a',\n              repo: 'uipkge',\n              status: 'completed',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-gh-004',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"total_count\":24,\"workflow_runs\":[{\"id\":9812401,\"name\":\"CI Registry Build\",\"conclusion\":\"success\"}]}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n  {\n    id: 'server-cf-4',\n    name: 'mcp/cloudflare-deployer',\n    scope: '@cloudflare/mcp-pages-worker',\n    version: 'v3.0.4',\n    transport: 'sse',\n    commandOrUrl: 'https://mcp-gateway.cloudflare.com/sse/v1/uipkge-prod',\n    status: 'healthy',\n    uptime: '100.0%',\n    latencyMs: 48,\n    callsToday: 1180,\n    description:\n      'Edge runtime deployment automation, real-time Cloudflare Worker telemetry log tailing, and CDN cache invalidation.',\n    envVars: ['CLOUDFLARE_API_TOKEN=cft_live_***', 'CLOUDFLARE_ACCOUNT_ID=8bb9e07a...'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'cloudflare://zones/{zoneId}/pages',\n        name: 'Pages Deployment Manifest',\n        description: 'Active production and preview deployment bundles with rollback pointers',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'cloudflare://workers/{scriptName}/tail',\n        name: 'Live Worker Telemetry Stream',\n        description: 'Real-time structured event logs, CPU execution times, and exceptions',\n        mimeType: 'application/x-ndjson',\n      },\n    ],\n    tools: [\n      {\n        name: 'deploy_pages',\n        displayName: 'Deploy Cloudflare Pages',\n        description: 'Triggers atomic Cloudflare Pages deployment bundle upload with verification.',\n        category: 'deployment',\n        parameters: [\n          {\n            name: 'projectName',\n            type: 'string',\n            required: true,\n            description: 'Cloudflare Pages project name (uipkge).',\n          },\n          { name: 'branch', type: 'string', required: true, description: 'Git branch trigger (e.g. main).' },\n          { name: 'commitHash', type: 'string', required: true, description: 'Target 40-char Git commit hash.' },\n          {\n            name: 'environment',\n            type: 'string',\n            required: false,\n            default: 'production',\n            enum: ['production', 'preview'],\n            description: 'Deployment target stage.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-cf-001',\n          method: 'tools/call',\n          params: {\n            name: 'deploy_pages',\n            arguments: {\n              projectName: 'uipkge',\n              branch: 'main',\n              commitHash: '7c8b91a24d0e932b12f4567890abcdef12345678',\n              environment: 'production',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-cf-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"deploymentId\":\"dep_9801a\",\"url\":\"https://uipkge.dev\",\"status\":\"active\",\"buildDurationSec\":14}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'purge_cache',\n        displayName: 'Purge CDN Cache',\n        description: 'Purges Cloudflare CDN cache zones by URL pattern or Cache-Tag headers.',\n        category: 'deployment',\n        parameters: [\n          { name: 'zoneId', type: 'string', required: true, description: 'Cloudflare Zone identifier.' },\n          {\n            name: 'purgeEverything',\n            type: 'boolean',\n            required: false,\n            default: 'false',\n            description: 'Purge entire CDN edge cache.',\n          },\n          { name: 'tags', type: 'array', required: false, description: 'Array of Cache-Tag headers to invalidate.' },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-cf-002',\n          method: 'tools/call',\n          params: {\n            name: 'purge_cache',\n            arguments: {\n              zoneId: 'zn_uipkge_core_912',\n              purgeEverything: false,\n              tags: ['registry-json', 'llms-txt'],\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-cf-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"success\":true,\"purgedTags\":[\"registry-json\",\"llms-txt\"],\"timestamp\":\"2026-08-21T10:45:00Z\"}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'tail_worker_logs',\n        displayName: 'Tail Worker Logs',\n        description: 'Subscribes to real-time Cloudflare Worker telemetry logs and exception traces.',\n        category: 'deployment',\n        parameters: [\n          { name: 'scriptName', type: 'string', required: true, description: 'Worker script identifier.' },\n          {\n            name: 'samplingRate',\n            type: 'number',\n            required: false,\n            default: '1.0',\n            description: 'Trace event sampling ratio (0.1 to 1.0).',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-cf-003',\n          method: 'tools/call',\n          params: {\n            name: 'tail_worker_logs',\n            arguments: {\n              scriptName: 'uipkge-registry-proxy',\n              samplingRate: 1.0,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-cf-003',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"sessionId\":\"tail_sess_904\",\"status\":\"streaming\",\"eventsProcessed\":480}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n  {\n    id: 'server-bv-5',\n    name: 'mcp/brave-search',\n    scope: '@modelcontextprotocol/server-brave-search',\n    version: 'v1.1.2',\n    transport: 'sse',\n    commandOrUrl: 'https://mcp-stream.brave.internal/sse?channel=research',\n    status: 'reconnecting',\n    uptime: '98.40%',\n    latencyMs: 165,\n    callsToday: 840,\n    description: 'Privacy-preserving web search, index lookup, and clean markdown extraction from live URLs.',\n    envVars: ['BRAVE_API_KEY=bsa_live_***', 'RATE_LIMIT_RPS=20'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'search://web/{query}',\n        name: 'Real-Time Web Search Cache',\n        description: 'Cached organic search result nodes with domain trust rankings',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'webpage://cached/{urlHash}',\n        name: 'Normalized Page Mirror',\n        description: 'Clean reader-mode markdown representation of fetched webpage',\n        mimeType: 'text/markdown',\n      },\n    ],\n    tools: [\n      {\n        name: 'brave_search',\n        displayName: 'Brave Web Search',\n        description: 'Queries Brave Search API for web results, snippets, publishing dates, and ranking scores.',\n        category: 'web-search',\n        parameters: [\n          { name: 'query', type: 'string', required: true, description: 'Search term or technical keyword.' },\n          {\n            name: 'count',\n            type: 'number',\n            required: false,\n            default: '10',\n            description: 'Number of organic results (1-20).',\n          },\n          {\n            name: 'freshness',\n            type: 'string',\n            required: false,\n            enum: ['pd', 'pw', 'pm', 'py'],\n            description: 'Filter by time horizon: past day, week, month, or year.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-bv-001',\n          method: 'tools/call',\n          params: {\n            name: 'brave_search',\n            arguments: {\n              query: 'Reka UI Vue 3.5 release notes',\n              count: 5,\n              freshness: 'pm',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-bv-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"results\":[{\"title\":\"Reka UI v1.4 Documentation\",\"url\":\"https://reka-ui.com\",\"snippet\":\"Radix-vue is now Reka UI with Vue 3.5 TypeScript improvements.\"}]}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'fetch_web_content',\n        displayName: 'Fetch Web Content',\n        description: 'Fetches full clean markdown representations from verified web URLs.',\n        category: 'web-search',\n        parameters: [\n          { name: 'url', type: 'string', required: true, description: 'Fully qualified HTTP/HTTPS URL to crawl.' },\n          {\n            name: 'format',\n            type: 'string',\n            required: false,\n            default: 'markdown',\n            enum: ['markdown', 'text', 'html'],\n            description: 'Target format of extracted webpage body content.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-bv-002',\n          method: 'tools/call',\n          params: {\n            name: 'fetch_web_content',\n            arguments: {\n              url: 'https://modelcontextprotocol.io/introduction',\n              format: 'markdown',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-bv-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '# Model Context Protocol\\n\\nMCP is an open standard that enables developers to build secure, two-way connections between their data sources and AI-powered tools.',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n  {\n    id: 'server-sn-6',\n    name: 'mcp/sentry-telemetry',\n    scope: '@sentry/mcp-telemetry',\n    version: 'v1.8.0',\n    transport: 'stdio',\n    commandOrUrl: 'npx -y @sentry/mcp-telemetry --org=uipkge',\n    status: 'healthy',\n    uptime: '99.99%',\n    latencyMs: 35,\n    callsToday: 820,\n    description:\n      'Production crash monitoring, unhandled exceptions triage, and stacktrace source-mapping for AI agents.',\n    envVars: ['SENTRY_AUTH_TOKEN=sntrys_live_***', 'SENTRY_ORG=uipkge'],\n    resourceTemplates: [\n      {\n        uriTemplate: 'sentry://projects/{project}/issues/{issueId}',\n        name: 'Sentry Issue Context',\n        description: 'Resolved source maps, breadcrumbs trail, device context, and user impact rate',\n        mimeType: 'application/json',\n      },\n      {\n        uriTemplate: 'sentry://projects/{project}/stats/24h',\n        name: 'Hourly Error Volume',\n        description: 'Aggregated error frequency histograms across release versions',\n        mimeType: 'application/json',\n      },\n    ],\n    tools: [\n      {\n        name: 'query_sentry_issues',\n        displayName: 'Query Sentry Issues',\n        description: 'Lists unhandled exceptions and regression issues by release tag and frequency.',\n        category: 'observability',\n        parameters: [\n          { name: 'project', type: 'string', required: true, description: 'Sentry project slug.' },\n          { name: 'query', type: 'string', required: false, description: 'Sentry search query (e.g. is:unresolved).' },\n          {\n            name: 'statsPeriod',\n            type: 'string',\n            required: false,\n            default: '24h',\n            enum: ['24h', '14d', '30d'],\n            description: 'Time window for issue occurrence statistics.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-sn-001',\n          method: 'tools/call',\n          params: {\n            name: 'query_sentry_issues',\n            arguments: {\n              project: 'uipkge-astro-site',\n              query: 'is:unresolved level:error',\n              statsPeriod: '24h',\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-sn-001',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"issues\":[{\"id\":\"iss_991\",\"title\":\"TypeError: Cannot read properties of undefined (reading \\'dataset\\')\",\"count\":3,\"lastSeen\":\"2026-08-21T09:12:00Z\"}]}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n      {\n        name: 'get_issue_stacktrace',\n        displayName: 'Get De-minified Stacktrace',\n        description: 'Retrieves de-minified source code stacktrace and breadcrumb chain for an error ID.',\n        category: 'observability',\n        parameters: [\n          { name: 'issueId', type: 'string', required: true, description: 'Unique Sentry issue identifier.' },\n          {\n            name: 'expandContext',\n            type: 'boolean',\n            required: false,\n            default: 'true',\n            description: 'Include 5 lines of source code surrounding the crashing line.',\n          },\n        ],\n        sampleRpcRequest: {\n          jsonrpc: '2.0',\n          id: 'req-sn-002',\n          method: 'tools/call',\n          params: {\n            name: 'get_issue_stacktrace',\n            arguments: {\n              issueId: 'iss_991',\n              expandContext: true,\n            },\n          },\n        },\n        sampleRpcResponse: {\n          jsonrpc: '2.0',\n          id: 'req-sn-002',\n          result: {\n            content: [\n              {\n                type: 'text',\n                text: '{\"filename\":\"src/components/story/Story.tsx\",\"lineno\":42,\"colno\":14,\"function\":\"handleCopy\",\"contextLine\":\"navigator.clipboard.writeText(props.code)\"}',\n              },\n            ],\n            isError: false,\n          },\n        },\n      },\n    ],\n  },\n]\n\nexport function McpServerRegistryManager({\n  className,\n  initialSearch = '',\n  initialTransportFilter = 'all',\n  initialStatusFilter = 'all',\n  initialSelectedToolName,\n  initialDrawerOpen = false,\n  initialInstallDialogOpen = false,\n  initialHandshakeAlert = false,\n  initialServers,\n}: McpServerRegistryManagerProps) {\n  const [servers, setServers] = React.useState<McpServer[]>(() =>\n    initialServers ? [...initialServers] : [...defaultServers],\n  )\n  const [searchQuery, setSearchQuery] = React.useState(initialSearch)\n  const [transportFilter, setTransportFilter] = React.useState<'all' | 'stdio' | 'sse'>(initialTransportFilter)\n  const [statusFilter, setStatusFilter] = React.useState<'all' | 'healthy' | 'reconnecting'>(initialStatusFilter)\n  const [isDrawerOpen, setIsDrawerOpen] = React.useState(initialDrawerOpen)\n  const [isInstallDialogOpen, setIsInstallDialogOpen] = React.useState(initialInstallDialogOpen)\n  const [handshakeAlertVisible, setHandshakeAlertVisible] = React.useState(initialHandshakeAlert)\n  const [isHandshaking, setIsHandshaking] = React.useState(false)\n  const [copiedKey, setCopiedKey] = React.useState<string | null>(null)\n  const [inspectorTab, setInspectorTab] = React.useState<'request' | 'response' | 'schema'>('request')\n  const [activeViewTab, setActiveViewTab] = React.useState<'servers' | 'handshake-logs' | 'config-json'>('servers')\n\n  // Selected tool & server for the schema drawer\n  const [selectedServer, setSelectedServer] = React.useState<McpServer>(() => {\n    if (initialSelectedToolName) {\n      for (const s of defaultServers) {\n        if (s.tools.some((t) => t.name === initialSelectedToolName)) return s\n      }\n    }\n    return defaultServers[0]\n  })\n\n  const [selectedTool, setSelectedTool] = React.useState<ToolSchema>(() => {\n    if (initialSelectedToolName) {\n      for (const s of defaultServers) {\n        const found = s.tools.find((t) => t.name === initialSelectedToolName)\n        if (found) return found\n      }\n    }\n    return defaultServers[0].tools[0]\n  })\n\n  // New server form inputs\n  const [newServerName, setNewServerName] = React.useState('')\n  const [newServerScope, setNewServerScope] = React.useState('')\n  const [newTransport, setNewTransport] = React.useState<TransportType>('stdio')\n  const [newCommandOrUrl, setNewCommandOrUrl] = React.useState('')\n  const [newDescription, setNewDescription] = React.useState('')\n\n  // Dry run simulation\n  const [isDryRunning, setIsDryRunning] = React.useState(false)\n  const [dryRunOutput, setDryRunOutput] = React.useState<string | null>(null)\n\n  // Filtering Logic\n  const filteredServers = React.useMemo(() => {\n    const q = searchQuery.trim().toLowerCase()\n    return servers.filter((s) => {\n      const matchTransport = transportFilter === 'all' || s.transport === transportFilter\n      const matchStatus = statusFilter === 'all' || s.status === statusFilter\n      if (!matchTransport || !matchStatus) return false\n\n      if (!q) return true\n      const inName = s.name.toLowerCase().includes(q)\n      const inScope = s.scope.toLowerCase().includes(q)\n      const inDesc = s.description.toLowerCase().includes(q)\n      const inCmd = s.commandOrUrl.toLowerCase().includes(q)\n      const inTools = s.tools.some((t) => t.name.toLowerCase().includes(q) || t.displayName.toLowerCase().includes(q))\n      const inUris = s.resourceTemplates.some((r) => r.uriTemplate.toLowerCase().includes(q))\n      return inName || inScope || inDesc || inCmd || inTools || inUris\n    })\n  }, [servers, searchQuery, transportFilter, statusFilter])\n\n  // Counts\n  const totalConnectedServers = React.useMemo(() => servers.filter((s) => s.status === 'healthy').length, [servers])\n  const totalRegisteredTools = React.useMemo(() => servers.reduce((acc, s) => acc + s.tools.length, 0), [servers])\n\n  const openToolInspector = React.useCallback((server: McpServer, tool: ToolSchema) => {\n    setSelectedServer(server)\n    setSelectedTool(tool)\n    setDryRunOutput(null)\n    setIsDrawerOpen(true)\n  }, [])\n\n  const openServerInspector = React.useCallback((server: McpServer) => {\n    if (server.tools.length > 0) {\n      setSelectedServer(server)\n      setSelectedTool(server.tools[0])\n      setDryRunOutput(null)\n      setIsDrawerOpen(true)\n    }\n  }, [])\n\n  const copyToClipboard = React.useCallback((text: string, key: string) => {\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      navigator.clipboard.writeText(text)\n      setCopiedKey(key)\n      setTimeout(() => {\n        setCopiedKey((prev) => (prev === key ? null : prev))\n      }, 2000)\n    }\n  }, [])\n\n  const runHandshakeTest = React.useCallback(() => {\n    setIsHandshaking(true)\n    setHandshakeAlertVisible(false)\n    setTimeout(() => {\n      setIsHandshaking(false)\n      setHandshakeAlertVisible(true)\n    }, 650)\n  }, [])\n\n  const handleAddServer = React.useCallback(() => {\n    if (!newServerName.trim() || !newCommandOrUrl.trim()) return\n\n    const newServer: McpServer = {\n      id: `server-${Date.now()}`,\n      name: newServerName.trim(),\n      scope: newServerScope.trim() || `@custom/${newServerName.replace(/^mcp\\//, '')}`,\n      version: 'v1.0.0',\n      transport: newTransport,\n      commandOrUrl: newCommandOrUrl.trim(),\n      status: 'healthy',\n      uptime: '100.0%',\n      latencyMs: newTransport === 'stdio' ? 22 : 64,\n      callsToday: 0,\n      description: newDescription.trim() || 'Custom registered Model Context Protocol runtime server.',\n      envVars: ['MCP_ENABLED=true'],\n      resourceTemplates: [\n        {\n          uriTemplate: `custom://${newServerName.replace(/^mcp\\//, '')}/{resourceId}`,\n          name: 'Custom Parameterized Resource',\n          description: 'Dynamic schema endpoint for custom tool payloads',\n          mimeType: 'application/json',\n        },\n      ],\n      tools: [\n        {\n          name: `${newServerName.replace(/^mcp\\//, '').replace(/[^a-zA-Z0-9_]/g, '_')}_action`,\n          displayName: 'Execute Custom Action',\n          description: 'Default action handler registered for this server.',\n          category: 'deployment',\n          parameters: [{ name: 'payload', type: 'string', required: true, description: 'Action parameter payload.' }],\n          sampleRpcRequest: {\n            jsonrpc: '2.0',\n            id: 'req-custom-001',\n            method: 'tools/call',\n            params: {\n              name: `${newServerName.replace(/^mcp\\//, '').replace(/[^a-zA-Z0-9_]/g, '_')}_action`,\n              arguments: { payload: 'execute' },\n            },\n          },\n          sampleRpcResponse: {\n            jsonrpc: '2.0',\n            id: 'req-custom-001',\n            result: {\n              content: [{ type: 'text', text: '{\"status\":\"success\",\"executedAt\":\"2026-08-21T12:00:00Z\"}' }],\n              isError: false,\n            },\n          },\n        },\n      ],\n    }\n\n    setServers((prev) => [newServer, ...prev])\n    setNewServerName('')\n    setNewServerScope('')\n    setNewCommandOrUrl('')\n    setNewDescription('')\n    setIsInstallDialogOpen(false)\n  }, [newServerName, newServerScope, newTransport, newCommandOrUrl, newDescription])\n\n  const removeServer = React.useCallback((serverId: string) => {\n    setServers((prev) => prev.filter((s) => s.id !== serverId))\n  }, [])\n\n  const restartServer = React.useCallback((server: McpServer) => {\n    setServers((prev) =>\n      prev.map((s) =>\n        s.id === server.id ? { ...s, status: 'healthy', latencyMs: Math.floor(Math.random() * 20) + 15 } : s,\n      ),\n    )\n  }, [])\n\n  const runDryRunTest = React.useCallback(() => {\n    if (!selectedTool) return\n    setIsDryRunning(true)\n    setTimeout(() => {\n      setIsDryRunning(false)\n      setDryRunOutput(JSON.stringify(selectedTool.sampleRpcResponse.result, null, 2))\n    }, 450)\n  }, [selectedTool])\n\n  const activeMcpConfigJson = React.useMemo(() => {\n    const config: { mcpServers: Record<string, any> } = { mcpServers: {} }\n    for (const s of servers) {\n      const key = s.name.replace(/^mcp\\//, '')\n      if (s.transport === 'stdio') {\n        const parts = s.commandOrUrl.split(' ')\n        config.mcpServers[key] = {\n          command: parts[0],\n          args: parts.slice(1),\n          env: s.envVars.reduce((acc: Record<string, string>, ev) => {\n            const [k, v] = ev.split('=')\n            if (k && v) acc[k] = v\n            return acc\n          }, {}),\n        }\n      } else {\n        config.mcpServers[key] = {\n          transport: 'sse',\n          url: s.commandOrUrl,\n        }\n      }\n    }\n    return JSON.stringify(config, null, 2)\n  }, [servers])\n\n  return (\n    <div\n      data-slot=\"mcp-server-registry-manager\"\n      className={cn(\n        'bg-background text-foreground border-border w-full space-y-6 overflow-hidden rounded-xl border p-4 shadow-xs sm:p-6 md:p-8',\n        className,\n      )}\n    >\n      {/* Top System Header */}\n      <header className=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n        <div className=\"space-y-1.5\">\n          <div className=\"flex flex-wrap items-center gap-2.5\">\n            <div className=\"bg-primary/10 text-primary border-primary/20 flex size-9 items-center justify-center rounded-lg border\">\n              <Server className=\"size-4.5\" />\n            </div>\n            <h1 className=\"text-xl font-bold tracking-tight sm:text-2xl\">\n              Model Context Protocol (MCP) Server Manager\n            </h1>\n          </div>\n          <div className=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs\">\n            <Badge variant=\"secondary\" className=\"font-mono text-xs font-normal\">\n              MCP Spec 2024-11-05 · JSON-RPC 2.0\n            </Badge>\n            <span>•</span>\n            <span className=\"text-success inline-flex items-center gap-1.5 font-medium\">\n              <span className=\"bg-success flex size-2 animate-pulse rounded-full\" />\n              {totalConnectedServers} Connected · {totalRegisteredTools} Tools Active\n            </span>\n            <span className=\"hidden sm:inline\">•</span>\n            <span className=\"hidden sm:inline\">Anthropic Runtime & Agent Registry</span>\n          </div>\n        </div>\n\n        {/* Action CTA Buttons */}\n        <div className=\"flex flex-wrap items-center gap-2.5\">\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"h-9 gap-1.5 text-xs font-medium\"\n            disabled={isHandshaking}\n            onClick={runHandshakeTest}\n          >\n            <RefreshCw className={cn('size-3.5', isHandshaking && 'text-primary animate-spin')} />\n            <span>{isHandshaking ? 'Handshaking...' : 'Test Tool Handshake'}</span>\n          </Button>\n\n          <Button\n            size=\"sm\"\n            className=\"h-9 gap-1.5 text-xs font-medium shadow-xs\"\n            onClick={() => setIsInstallDialogOpen(true)}\n          >\n            <Plus className=\"size-3.5\" />\n            <span>Install New MCP Server</span>\n          </Button>\n        </div>\n      </header>\n\n      {/* Handshake Diagnostic Alert Banner */}\n      {handshakeAlertVisible && (\n        <div className=\"border-success/30 bg-success/10 text-foreground dark:text-foreground flex items-start justify-between rounded-lg border p-3.5 text-xs transition-colors\">\n          <div className=\"flex items-start gap-2.5\">\n            <CheckCircle2 className=\"text-success mt-0.5 size-4 shrink-0\" />\n            <div className=\"space-y-0.5\">\n              <p className=\"text-success font-semibold\">Handshake Verified · All 6 MCP Servers Responded (Avg 42ms)</p>\n              <p className=\"text-success\">\n                34 tool schemas, 18 resource templates, and prompt interfaces validated against MCP Specification\n                2024-11-05.\n              </p>\n            </div>\n          </div>\n          <button\n            type=\"button\"\n            aria-label=\"Dismiss notification\"\n            className=\"text-success hover:text-foreground rounded-md p-1 transition-colors\"\n            onClick={() => setHandshakeAlertVisible(false)}\n          >\n            <X className=\"size-3.5\" />\n          </button>\n        </div>\n      )}\n\n      {/* 4 MCP System KPI Cards */}\n      <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n        {/* KPI 1: Connected MCP Servers */}\n        <Card className=\"border-border bg-card shadow-xs\">\n          <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n            <CardTitle className=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n              Connected Servers\n            </CardTitle>\n            <div className=\"bg-primary/10 text-primary flex size-7 items-center justify-center rounded-md\">\n              <Server className=\"size-3.5\" />\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-1\">\n            <div className=\"text-2xl font-bold tracking-tight\">{servers.length} Active Servers</div>\n            <div className=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n              <span className=\"bg-success inline-block size-1.5 rounded-full\" />\n              <span>{totalConnectedServers} healthy</span>\n              <span>•</span>\n              <span className=\"text-warning\">1 reconnecting</span>\n            </div>\n          </CardContent>\n        </Card>\n\n        {/* KPI 2: Registered Tools */}\n        <Card className=\"border-border bg-card shadow-xs\">\n          <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n            <CardTitle className=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n              Registered Tools\n            </CardTitle>\n            <div className=\"bg-primary/10 text-primary flex size-7 items-center justify-center rounded-md\">\n              <Wrench className=\"size-3.5\" />\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-1\">\n            <div className=\"text-2xl font-bold tracking-tight\">34 Tool Functions</div>\n            <div className=\"text-success flex items-center gap-1.5 text-xs\">\n              <ShieldCheck className=\"size-3.5\" />\n              <span>100% Schema Validated</span>\n            </div>\n          </CardContent>\n        </Card>\n\n        {/* KPI 3: Resource Templates */}\n        <Card className=\"border-border bg-card shadow-xs\">\n          <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n            <CardTitle className=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n              Resource Templates\n            </CardTitle>\n            <div className=\"bg-primary/10 text-primary flex size-7 items-center justify-center rounded-md\">\n              <Link2 className=\"size-3.5\" />\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-1\">\n            <div className=\"text-2xl font-bold tracking-tight\">18 Parameterized URIs</div>\n            <div className=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n              <Boxes className=\"size-3.5\" />\n              <span>Dynamic URI Subscriptions</span>\n            </div>\n          </CardContent>\n        </Card>\n\n        {/* KPI 4: Tool Invocation Volume */}\n        <Card className=\"border-border bg-card shadow-xs\">\n          <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n            <CardTitle className=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n              Invocation Volume\n            </CardTitle>\n            <div className=\"bg-primary/10 text-primary flex size-7 items-center justify-center rounded-md\">\n              <Zap className=\"size-3.5\" />\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-1\">\n            <div className=\"text-2xl font-bold tracking-tight\">12,480 calls today</div>\n            <div className=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n              <Activity className=\"text-success size-3.5\" />\n              <span className=\"text-foreground font-medium\">99.8%</span> success · 142ms avg\n            </div>\n          </CardContent>\n        </Card>\n      </div>\n\n      {/* Main Content Navigation & Filter Bar */}\n      <div className=\"space-y-4\">\n        <div className=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n          {/* View Tabs */}\n          <Tabs\n            value={activeViewTab}\n            onValueChange={(val) => setActiveViewTab(val as any)}\n            className=\"w-full md:w-auto\"\n          >\n            <TabsList className=\"grid h-9 w-full grid-cols-3 md:w-[380px]\">\n              <TabsTrigger value=\"servers\" className=\"text-xs\">\n                Servers & Tools ({servers.length})\n              </TabsTrigger>\n              <TabsTrigger value=\"handshake-logs\" className=\"text-xs\">\n                Handshake Logs\n              </TabsTrigger>\n              <TabsTrigger value=\"config-json\" className=\"text-xs\">\n                Raw JSON Config\n              </TabsTrigger>\n            </TabsList>\n          </Tabs>\n\n          {/* Search Bar and Transport Filters */}\n          <div className=\"flex flex-wrap items-center gap-2\">\n            <div className=\"relative w-full sm:w-64\">\n              <Search className=\"text-muted-foreground absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2\" />\n              <Input\n                value={searchQuery}\n                onChange={(e) => setSearchQuery(e.target.value)}\n                placeholder=\"Search servers, tools, URIs...\"\n                className=\"bg-background h-8.5 pl-8 text-xs\"\n              />\n            </div>\n\n            {/* Transport Filter Buttons */}\n            <div className=\"border-border bg-muted/40 flex items-center rounded-lg border p-0.5 text-xs\">\n              <button\n                type=\"button\"\n                className={cn(\n                  'rounded-md px-2.5 py-1 font-medium transition-colors',\n                  transportFilter === 'all'\n                    ? 'bg-background text-foreground shadow-xs'\n                    : 'text-muted-foreground hover:text-foreground',\n                )}\n                onClick={() => setTransportFilter('all')}\n              >\n                All\n              </button>\n              <button\n                type=\"button\"\n                className={cn(\n                  'inline-flex items-center gap-1 rounded-md px-2.5 py-1 font-medium transition-colors',\n                  transportFilter === 'stdio'\n                    ? 'bg-background text-foreground shadow-xs'\n                    : 'text-muted-foreground hover:text-foreground',\n                )}\n                onClick={() => setTransportFilter('stdio')}\n              >\n                <Terminal className=\"size-3\" />\n                stdio\n              </button>\n              <button\n                type=\"button\"\n                className={cn(\n                  'inline-flex items-center gap-1 rounded-md px-2.5 py-1 font-medium transition-colors',\n                  transportFilter === 'sse'\n                    ? 'bg-background text-foreground shadow-xs'\n                    : 'text-muted-foreground hover:text-foreground',\n                )}\n                onClick={() => setTransportFilter('sse')}\n              >\n                <Radio className=\"size-3\" />\n                SSE Stream\n              </button>\n            </div>\n          </div>\n        </div>\n\n        {/* Tab View 1: Servers & Tools List */}\n        {activeViewTab === 'servers' && (\n          <div className=\"space-y-4\">\n            {/* Empty State */}\n            {filteredServers.length === 0 && (\n              <div className=\"border-border bg-card/40 flex flex-col items-center justify-center rounded-xl border border-dashed p-10 text-center\">\n                <Server className=\"text-muted-foreground/60 mb-3 size-10\" />\n                <h3 className=\"text-sm font-semibold\">No MCP Servers Found</h3>\n                <p className=\"text-muted-foreground mt-1 max-w-sm text-xs\">\n                  No servers match your current search query or filter criteria. Clear filters or add a new MCP server\n                  connection.\n                </p>\n                <Button\n                  size=\"sm\"\n                  variant=\"outline\"\n                  className=\"mt-4 h-8 text-xs\"\n                  onClick={() => {\n                    setSearchQuery('')\n                    setTransportFilter('all')\n                    setStatusFilter('all')\n                  }}\n                >\n                  Reset Filters\n                </Button>\n              </div>\n            )}\n\n            {/* Servers Cards */}\n            {filteredServers.map((server) => (\n              <div\n                key={server.id}\n                className=\"border-border bg-card hover:border-border/80 space-y-3.5 rounded-xl border p-4 shadow-xs transition-colors\"\n              >\n                {/* Server Header Line */}\n                <div className=\"flex flex-col gap-2.5 sm:flex-row sm:items-center sm:justify-between\">\n                  <div className=\"flex flex-wrap items-center gap-2.5\">\n                    <div className=\"bg-muted text-foreground border-border flex size-8 items-center justify-center rounded-lg border\">\n                      {server.transport === 'stdio' ? (\n                        <Terminal className=\"size-4\" />\n                      ) : (\n                        <Radio className=\"text-info size-4\" />\n                      )}\n                    </div>\n                    <div>\n                      <div className=\"flex items-center gap-2\">\n                        <span className=\"text-foreground font-mono text-sm font-semibold tracking-tight\">\n                          {{ ...server }.name}\n                        </span>\n                        <Badge variant=\"secondary\" className=\"font-mono text-xs font-normal\">\n                          {server.version}\n                        </Badge>\n                        <Badge\n                          variant={server.transport === 'stdio' ? 'outline' : 'secondary'}\n                          className=\"gap-1 font-mono text-xs\"\n                        >\n                          {server.transport === 'stdio' ? (\n                            <Terminal className=\"size-3\" />\n                          ) : (\n                            <Radio className=\"text-info size-3\" />\n                          )}\n                          {server.transport === 'stdio' ? 'stdio' : 'SSE stream'}\n                        </Badge>\n                      </div>\n                      <p className=\"text-muted-foreground mt-0.5 text-xs\">\n                        {server.scope} · {server.description}\n                      </p>\n                    </div>\n                  </div>\n\n                  {/* Status and Dropdown Actions */}\n                  <div className=\"flex items-center gap-2 sm:self-center\">\n                    {server.status === 'healthy' ? (\n                      <Badge variant=\"outline\" className=\"border-success/40 bg-success/10 text-success gap-1.5 text-xs\">\n                        <span className=\"bg-success size-1.5 rounded-full\" />\n                        Connected & Healthy\n                      </Badge>\n                    ) : (\n                      <Badge variant=\"outline\" className=\"border-warning/40 bg-warning/10 text-warning gap-1.5 text-xs\">\n                        <span className=\"bg-warning size-1.5 rounded-full\" />\n                        Reconnecting ({server.latencyMs}ms)\n                      </Badge>\n                    )}\n\n                    <DropdownMenu>\n                      <DropdownMenuTrigger asChild>\n                        <Button variant=\"ghost\" size=\"icon\" className=\"size-8\">\n                          <MoreHorizontal className=\"size-4\" />\n                          <span className=\"sr-only\">Server Options</span>\n                        </Button>\n                      </DropdownMenuTrigger>\n                      <DropdownMenuContent align=\"end\" className=\"w-48 text-xs\">\n                        <DropdownMenuLabel>Server Actions</DropdownMenuLabel>\n                        <DropdownMenuItem onClick={() => openServerInspector(server)}>\n                          <FileCode className=\"mr-2 size-3.5\" />\n                          Inspect Tool Schema\n                        </DropdownMenuItem>\n                        <DropdownMenuItem onClick={() => restartServer(server)}>\n                          <RefreshCw className=\"mr-2 size-3.5\" />\n                          Restart Process\n                        </DropdownMenuItem>\n                        <DropdownMenuItem onClick={() => copyToClipboard(server.commandOrUrl, `cmd-${server.id}`)}>\n                          <Copy className=\"mr-2 size-3.5\" />\n                          {copiedKey === `cmd-${server.id}` ? 'Copied Command!' : 'Copy Command'}\n                        </DropdownMenuItem>\n                        <DropdownMenuSeparator />\n                        <DropdownMenuItem\n                          className=\"text-destructive focus:text-destructive\"\n                          onClick={() => removeServer(server.id)}\n                        >\n                          <Trash2 className=\"mr-2 size-3.5\" />\n                          Disconnect Server\n                        </DropdownMenuItem>\n                      </DropdownMenuContent>\n                    </DropdownMenu>\n                  </div>\n                </div>\n\n                {/* Command or Endpoint snippet */}\n                <div className=\"bg-muted/60 border-border flex items-center justify-between rounded-lg border px-3 py-2 font-mono text-xs\">\n                  <div className=\"flex items-center gap-2 overflow-x-auto\">\n                    <span className=\"text-muted-foreground select-none\">$</span>\n                    <span className=\"text-foreground truncate\">{server.commandOrUrl}</span>\n                  </div>\n                  <Button\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    className=\"ml-2 size-6 shrink-0\"\n                    onClick={() => copyToClipboard(server.commandOrUrl, `cmd-btn-${server.id}`)}\n                  >\n                    {copiedKey === `cmd-btn-${server.id}` ? (\n                      <Check className=\"text-success size-3\" />\n                    ) : (\n                      <Copy className=\"text-muted-foreground size-3\" />\n                    )}\n                  </Button>\n                </div>\n\n                {/* Resource Templates List */}\n                {server.resourceTemplates.length > 0 && (\n                  <div className=\"space-y-1.5\">\n                    <div className=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n                      <Link2 className=\"size-3\" />\n                      <span>Resource URI Templates:</span>\n                    </div>\n                    <div className=\"flex flex-wrap items-center gap-1.5\">\n                      {server.resourceTemplates.map((res) => (\n                        <div\n                          key={res.uriTemplate}\n                          className=\"bg-muted/40 border-border text-foreground hover:bg-muted inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 font-mono text-xs transition-colors\"\n                          title={res.description}\n                        >\n                          <span className=\"text-primary font-medium\">{res.uriTemplate}</span>\n                          <span className=\"text-muted-foreground font-sans text-xs\">({res.name})</span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                )}\n\n                {/* Registered Tool Badges & Inspector Triggers */}\n                <div className=\"flex flex-col gap-2 pt-1 sm:flex-row sm:items-center sm:justify-between\">\n                  <div className=\"flex flex-wrap items-center gap-1.5\">\n                    <span className=\"text-muted-foreground mr-1 text-xs font-medium\">\n                      Tools ({server.tools.length}):\n                    </span>\n                    {server.tools.map((tool) => (\n                      <button\n                        key={tool.name}\n                        type=\"button\"\n                        className=\"border-primary/30 bg-primary/5 hover:bg-primary/15 text-primary focus-visible:ring-ring inline-flex cursor-pointer items-center gap-1 rounded-md border px-2 py-1 font-mono text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-hidden\"\n                        onClick={() => openToolInspector(server, tool)}\n                      >\n                        <Code2 className=\"size-3\" />\n                        <span>{tool.name}</span>\n                      </button>\n                    ))}\n                  </div>\n\n                  {/* Inspect Action Button */}\n                  <div className=\"flex items-center gap-2\">\n                    <span className=\"text-muted-foreground hidden text-xs lg:inline\">\n                      {server.callsToday.toLocaleString()} calls · {server.latencyMs}ms ping\n                    </span>\n                    <Button\n                      variant=\"outline\"\n                      size=\"sm\"\n                      className=\"h-7.5 gap-1 text-xs\"\n                      onClick={() => openServerInspector(server)}\n                    >\n                      <Braces className=\"size-3.5\" />\n                      <span>Inspect Tool JSON Schema</span>\n                    </Button>\n                  </div>\n                </div>\n              </div>\n            ))}\n          </div>\n        )}\n\n        {/* Tab View 2: Handshake & Telemetry Logs */}\n        {activeViewTab === 'handshake-logs' && (\n          <div className=\"space-y-4\">\n            <Card className=\"border-border bg-card\">\n              <CardHeader className=\"pb-3\">\n                <div className=\"flex items-center justify-between\">\n                  <div>\n                    <CardTitle className=\"text-sm font-bold\">MCP Handshake & Protocol Event Stream</CardTitle>\n                    <CardDescription className=\"text-xs\">\n                      Real-time JSON-RPC 2.0 handshake pings and capability negotiation logs.\n                    </CardDescription>\n                  </div>\n                  <Button size=\"sm\" variant=\"outline\" className=\"h-8 gap-1.5 text-xs\" onClick={runHandshakeTest}>\n                    <RefreshCw className={cn('size-3.5', isHandshaking && 'animate-spin')} />\n                    Re-probe Connections\n                  </Button>\n                </div>\n              </CardHeader>\n              <CardContent className=\"p-0\">\n                <Table>\n                  <TableHeader>\n                    <TableRow className=\"hover:bg-transparent\">\n                      <TableHead className=\"text-xs\">Server / Scope</TableHead>\n                      <TableHead className=\"text-xs\">Transport</TableHead>\n                      <TableHead className=\"text-xs\">Handshake Status</TableHead>\n                      <TableHead className=\"text-xs\">Latency</TableHead>\n                      <TableHead className=\"text-xs\">Tools Validated</TableHead>\n                      <TableHead className=\"text-right text-xs\">Last Ping</TableHead>\n                    </TableRow>\n                  </TableHeader>\n                  <TableBody>\n                    {servers.map((s) => (\n                      <TableRow key={s.id} className=\"text-xs\">\n                        <TableCell className=\"font-mono font-medium\">{s.name}</TableCell>\n                        <TableCell>\n                          <Badge variant=\"secondary\" className=\"font-mono text-xs\">\n                            {s.transport}\n                          </Badge>\n                        </TableCell>\n                        <TableCell>\n                          <span\n                            className={cn(\n                              'inline-flex items-center gap-1.5 font-medium',\n                              s.status === 'healthy' ? 'text-success' : 'text-warning',\n                            )}\n                          >\n                            <span\n                              className={cn(\n                                'size-1.5 rounded-full',\n                                s.status === 'healthy' ? 'bg-success' : 'bg-warning',\n                              )}\n                            />\n                            {s.status === 'healthy' ? 'SYN_ACK 200 OK' : 'RETRY_BACKOFF'}\n                          </span>\n                        </TableCell>\n                        <TableCell className=\"text-muted-foreground font-mono\">{s.latencyMs}ms</TableCell>\n                        <TableCell>\n                          <span className=\"text-foreground font-medium\">{s.tools.length} schemas</span>\n                        </TableCell>\n                        <TableCell className=\"text-muted-foreground text-right\">Just now</TableCell>\n                      </TableRow>\n                    ))}\n                  </TableBody>\n                </Table>\n              </CardContent>\n            </Card>\n          </div>\n        )}\n\n        {/* Tab View 3: Raw JSON Configuration */}\n        {activeViewTab === 'config-json' && (\n          <div className=\"space-y-4\">\n            <Card className=\"border-border bg-card\">\n              <CardHeader className=\"pb-3\">\n                <div className=\"flex items-center justify-between\">\n                  <div>\n                    <CardTitle className=\"text-sm font-bold\">Claude Desktop & Cursor MCP Config</CardTitle>\n                    <CardDescription className=\"text-xs\">\n                      Exportable JSON format compatible with{' '}\n                      <code className=\"font-mono\">claude_desktop_config.json</code>.\n                    </CardDescription>\n                  </div>\n                  <Button\n                    size=\"sm\"\n                    variant=\"outline\"\n                    className=\"h-8 gap-1.5 text-xs\"\n                    onClick={() => copyToClipboard(activeMcpConfigJson, 'mcp-config-json')}\n                  >\n                    {copiedKey === 'mcp-config-json' ? (\n                      <Check className=\"text-success size-3.5\" />\n                    ) : (\n                      <Copy className=\"size-3.5\" />\n                    )}\n                    {copiedKey === 'mcp-config-json' ? 'JSON Copied!' : 'Copy Config JSON'}\n                  </Button>\n                </div>\n              </CardHeader>\n              <CardContent>\n                <pre className=\"bg-muted/60 border-border text-foreground max-h-[420px] overflow-x-auto rounded-lg border p-4 font-mono text-xs leading-relaxed\">\n                  {activeMcpConfigJson}\n                </pre>\n              </CardContent>\n            </Card>\n          </div>\n        )}\n      </div>\n\n      {/* Tool Schema Inspection Drawer (Sheet) */}\n      <McpToolInspectorDrawer\n        open={isDrawerOpen}\n        onOpenChange={setIsDrawerOpen}\n        server={selectedServer}\n        tool={selectedTool}\n        inspectorTab={inspectorTab}\n        onInspectorTabChange={setInspectorTab}\n        copiedKey={copiedKey}\n        onCopy={copyToClipboard}\n        isDryRunning={isDryRunning}\n        dryRunOutput={dryRunOutput}\n        onRunDryRun={runDryRunTest}\n      />\n\n      {/* Install New MCP Server Dialog */}\n      <Dialog open={isInstallDialogOpen} onOpenChange={setIsInstallDialogOpen}>\n        <DialogContent className=\"sm:max-w-lg\">\n          <DialogHeader className=\"space-y-1.5\">\n            <DialogTitle className=\"flex items-center gap-2 text-base font-bold\">\n              <Plus className=\"text-primary size-4\" />\n              Install New MCP Server\n            </DialogTitle>\n            <DialogDescription className=\"text-muted-foreground text-xs\">\n              Connect an Anthropic Model Context Protocol compliant local command or remote SSE stream.\n            </DialogDescription>\n          </DialogHeader>\n\n          <div className=\"space-y-3.5 py-2\">\n            <div className=\"space-y-1\">\n              <label className=\"text-foreground text-xs font-medium\">Server Identifier</label>\n              <Input\n                value={newServerName}\n                onChange={(e) => setNewServerName(e.target.value)}\n                placeholder=\"e.g. mcp/custom-inspector\"\n                className=\"h-8.5 font-mono text-xs\"\n              />\n            </div>\n\n            <div className=\"space-y-1\">\n              <label className=\"text-foreground text-xs font-medium\">Package Scope or Organization</label>\n              <Input\n                value={newServerScope}\n                onChange={(e) => setNewServerScope(e.target.value)}\n                placeholder=\"e.g. @org/mcp-server-custom\"\n                className=\"h-8.5 font-mono text-xs\"\n              />\n            </div>\n\n            <div className=\"space-y-1.5\">\n              <label className=\"text-foreground text-xs font-medium\">Transport Type</label>\n              <div className=\"grid grid-cols-2 gap-2\">\n                <button\n                  type=\"button\"\n                  className={cn(\n                    'flex items-center gap-2 rounded-lg border p-2.5 text-left text-xs transition-colors',\n                    newTransport === 'stdio'\n                      ? 'border-primary bg-primary/10 text-foreground font-semibold'\n                      : 'border-border bg-card text-muted-foreground hover:bg-muted',\n                  )}\n                  onClick={() => setNewTransport('stdio')}\n                >\n                  <Terminal className=\"text-primary size-4 shrink-0\" />\n                  <div>\n                    <div className=\"text-foreground font-medium\">stdio Subprocess</div>\n                    <div className=\"text-muted-foreground text-xs\">Local executable</div>\n                  </div>\n                </button>\n\n                <button\n                  type=\"button\"\n                  className={cn(\n                    'flex items-center gap-2 rounded-lg border p-2.5 text-left text-xs transition-colors',\n                    newTransport === 'sse'\n                      ? 'border-primary bg-primary/10 text-foreground font-semibold'\n                      : 'border-border bg-card text-muted-foreground hover:bg-muted',\n                  )}\n                  onClick={() => setNewTransport('sse')}\n                >\n                  <Radio className=\"text-info size-4 shrink-0\" />\n                  <div>\n                    <div className=\"text-foreground font-medium\">SSE HTTP Stream</div>\n                    <div className=\"text-muted-foreground text-xs\">Remote gateway</div>\n                  </div>\n                </button>\n              </div>\n            </div>\n\n            <div className=\"space-y-1\">\n              <label className=\"text-foreground text-xs font-medium\">\n                {newTransport === 'stdio' ? 'Command Line Entrypoint' : 'SSE Gateway URL'}\n              </label>\n              <Input\n                value={newCommandOrUrl}\n                onChange={(e) => setNewCommandOrUrl(e.target.value)}\n                placeholder={\n                  newTransport === 'stdio'\n                    ? 'npx -y @org/mcp-server --config=prod'\n                    : 'https://mcp.internal.company.com/sse/v1'\n                }\n                className=\"h-8.5 font-mono text-xs\"\n              />\n            </div>\n\n            <div className=\"space-y-1\">\n              <label className=\"text-foreground text-xs font-medium\">Server Description</label>\n              <Input\n                value={newDescription}\n                onChange={(e) => setNewDescription(e.target.value)}\n                placeholder=\"Short summary of tools and capabilities provided by this server\"\n                className=\"h-8.5 text-xs\"\n              />\n            </div>\n          </div>\n\n          <DialogFooter className=\"gap-2 sm:gap-0\">\n            <DialogClose asChild>\n              <Button variant=\"outline\" className=\"h-8.5 text-xs\">\n                Cancel\n              </Button>\n            </DialogClose>\n            <Button\n              className=\"h-8.5 text-xs\"\n              disabled={!newServerName.trim() || !newCommandOrUrl.trim()}\n              onClick={handleAddServer}\n            >\n              Register Server\n            </Button>\n          </DialogFooter>\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n\nexport default McpServerRegistryManager\n",
      "type": "registry:page",
      "target": "~/components/blocks/McpServerRegistryManager.tsx"
    },
    {
      "path": "packages/registry-react/blocks/mcp-server-registry-manager/McpToolInspectorDrawer.tsx",
      "content": "'use client'\n\nimport { Check, Code2, Copy, Play, RefreshCw } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Separator } from '@/components/ui/separator'\nimport {\n  Sheet,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n} from '@/components/ui/sheet'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\nimport type { McpServer, ToolSchema } from './McpServerRegistryManager'\n\nfunction getToolSchemaDraft7(tool: ToolSchema) {\n  const properties: Record<string, any> = {}\n  const required: string[] = []\n\n  for (const p of tool.parameters) {\n    properties[p.name] = {\n      type: p.type,\n      description: p.description,\n    }\n    if (p.default !== undefined) properties[p.name].default = p.default\n    if (p.enum) properties[p.name].enum = p.enum\n    if (p.required) required.push(p.name)\n  }\n\n  return {\n    $schema: 'http://json-schema.org/draft-07/schema#',\n    type: 'object',\n    properties,\n    required,\n    additionalProperties: false,\n  }\n}\n\nexport interface McpToolInspectorDrawerProps {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  server: McpServer\n  tool: ToolSchema\n  inspectorTab: 'request' | 'response' | 'schema'\n  onInspectorTabChange: (tab: 'request' | 'response' | 'schema') => void\n  copiedKey: string | null\n  onCopy: (text: string, key: string) => void\n  isDryRunning: boolean\n  dryRunOutput: string | null\n  onRunDryRun: () => void\n}\n\nexport function McpToolInspectorDrawer({\n  open,\n  onOpenChange,\n  server,\n  tool,\n  inspectorTab,\n  onInspectorTabChange,\n  copiedKey,\n  onCopy,\n  isDryRunning,\n  dryRunOutput,\n  onRunDryRun,\n}: McpToolInspectorDrawerProps) {\n  return (\n    <Sheet open={open} onOpenChange={onOpenChange}>\n      <SheetContent className=\"w-full space-y-6 overflow-y-auto p-6 sm:max-w-xl md:max-w-2xl\">\n        <SheetHeader className=\"space-y-2\">\n          <div className=\"flex flex-wrap items-center gap-2\">\n            <Badge variant=\"secondary\" className=\"font-mono text-xs font-medium\">\n              {server?.name}\n            </Badge>\n            <Badge variant=\"outline\" className=\"font-mono text-xs\">\n              {server?.transport}\n            </Badge>\n            <Badge className=\"bg-primary/10 text-primary border-primary/20 text-xs capitalize\" variant=\"outline\">\n              {tool?.category}\n            </Badge>\n          </div>\n          <SheetTitle className=\"text-foreground flex items-center gap-2 font-mono text-lg font-bold tracking-tight\">\n            <Code2 className=\"text-primary size-5\" />\n            <span>{tool?.name}</span>\n          </SheetTitle>\n          <SheetDescription className=\"text-muted-foreground text-xs leading-relaxed\">\n            {tool?.description}\n          </SheetDescription>\n        </SheetHeader>\n\n        <Separator />\n\n        {/* Parameters Specification Table */}\n        <div className=\"space-y-3\">\n          <div className=\"flex items-center justify-between\">\n            <h4 className=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n              Parameter Schema ({tool?.parameters.length})\n            </h4>\n            <span className=\"text-muted-foreground font-mono text-xs\">JSON-RPC 2.0 Method</span>\n          </div>\n\n          <div className=\"border-border overflow-hidden rounded-lg border\">\n            <Table>\n              <TableHeader className=\"bg-muted/40\">\n                <TableRow className=\"hover:bg-transparent\">\n                  <TableHead className=\"text-xs font-semibold\">Parameter</TableHead>\n                  <TableHead className=\"text-xs font-semibold\">Type</TableHead>\n                  <TableHead className=\"text-xs font-semibold\">Required</TableHead>\n                  <TableHead className=\"text-xs font-semibold\">Description</TableHead>\n                </TableRow>\n              </TableHeader>\n              <TableBody>\n                {tool?.parameters.map((param) => (\n                  <TableRow key={param.name} className=\"text-xs\">\n                    <TableCell className=\"text-foreground font-mono font-medium\">{param.name}</TableCell>\n                    <TableCell>\n                      <Badge variant=\"secondary\" className=\"font-mono text-xs\">\n                        {param.type}\n                      </Badge>\n                    </TableCell>\n                    <TableCell>\n                      <Badge\n                        variant={param.required ? 'default' : 'outline'}\n                        className={cn(\n                          'text-xs font-medium',\n                          param.required\n                            ? 'border-destructive/30 bg-destructive/10 text-destructive'\n                            : 'text-muted-foreground',\n                        )}\n                      >\n                        {param.required ? 'Required' : 'Optional'}\n                      </Badge>\n                    </TableCell>\n                    <TableCell className=\"text-muted-foreground\">\n                      <div>{param.description}</div>\n                      {param.default && (\n                        <div className=\"text-foreground/80 mt-0.5 font-mono text-xs\">\n                          default: <span className=\"text-primary\">{param.default}</span>\n                        </div>\n                      )}\n                      {param.enum && (\n                        <div className=\"text-foreground/80 mt-0.5 font-mono text-xs\">\n                          enum: [{param.enum.join(', ')}]\n                        </div>\n                      )}\n                    </TableCell>\n                  </TableRow>\n                ))}\n              </TableBody>\n            </Table>\n          </div>\n        </div>\n\n        {/* Tabbed JSON-RPC Schema & Payloads */}\n        <div className=\"space-y-3\">\n          <Tabs value={inspectorTab} onValueChange={(val) => onInspectorTabChange(val as any)} className=\"w-full\">\n            <div className=\"mb-2 flex items-center justify-between\">\n              <TabsList className=\"h-8\">\n                <TabsTrigger value=\"request\" className=\"text-xs\">\n                  Sample Request\n                </TabsTrigger>\n                <TabsTrigger value=\"response\" className=\"text-xs\">\n                  Sample Response\n                </TabsTrigger>\n                <TabsTrigger value=\"schema\" className=\"text-xs\">\n                  Draft-07 Schema\n                </TabsTrigger>\n              </TabsList>\n\n              <Button\n                variant=\"ghost\"\n                size=\"sm\"\n                className=\"h-7 gap-1 text-xs\"\n                onClick={() =>\n                  onCopy(\n                    inspectorTab === 'request'\n                      ? JSON.stringify(tool.sampleRpcRequest, null, 2)\n                      : inspectorTab === 'response'\n                        ? JSON.stringify(tool.sampleRpcResponse, null, 2)\n                        : JSON.stringify(getToolSchemaDraft7(tool), null, 2),\n                    'drawer-copied-schema',\n                  )\n                }\n              >\n                {copiedKey === 'drawer-copied-schema' ? (\n                  <Check className=\"text-success size-3\" />\n                ) : (\n                  <Copy className=\"size-3\" />\n                )}\n                {copiedKey === 'drawer-copied-schema' ? 'Copied!' : 'Copy Code'}\n              </Button>\n            </div>\n\n            {/* Tab 1: Request */}\n            <TabsContent value=\"request\" className=\"m-0\">\n              <pre className=\"bg-muted/60 border-border text-foreground max-h-56 overflow-x-auto rounded-lg border p-3.5 font-mono text-xs leading-relaxed\">\n                {JSON.stringify(tool?.sampleRpcRequest, null, 2)}\n              </pre>\n            </TabsContent>\n\n            {/* Tab 2: Response */}\n            <TabsContent value=\"response\" className=\"m-0\">\n              <pre className=\"bg-muted/60 border-border text-foreground max-h-56 overflow-x-auto rounded-lg border p-3.5 font-mono text-xs leading-relaxed\">\n                {JSON.stringify(tool?.sampleRpcResponse, null, 2)}\n              </pre>\n            </TabsContent>\n\n            {/* Tab 3: Draft-07 Schema */}\n            <TabsContent value=\"schema\" className=\"m-0\">\n              <pre className=\"bg-muted/60 border-border text-foreground max-h-56 overflow-x-auto rounded-lg border p-3.5 font-mono text-xs leading-relaxed\">\n                {JSON.stringify(getToolSchemaDraft7(tool), null, 2)}\n              </pre>\n            </TabsContent>\n          </Tabs>\n        </div>\n\n        {/* Dry Run Simulator */}\n        <div className=\"border-border bg-muted/20 space-y-3 rounded-lg border p-3.5\">\n          <div className=\"flex items-center justify-between\">\n            <span className=\"text-foreground flex items-center gap-1.5 text-xs font-semibold\">\n              <Play className=\"text-primary size-3.5\" />\n              Simulate Tool Invocation\n            </span>\n            <Button size=\"sm\" className=\"h-7.5 gap-1 text-xs\" disabled={isDryRunning} onClick={onRunDryRun}>\n              <RefreshCw className={cn('size-3', isDryRunning && 'animate-spin')} />\n              {isDryRunning ? 'Invoking RPC...' : 'Test Dry-Run Call'}\n            </Button>\n          </div>\n\n          {dryRunOutput && (\n            <div className=\"space-y-1\">\n              <span className=\"text-success font-mono text-xs\">✓ Invocation 200 OK (32ms):</span>\n              <pre className=\"bg-muted/80 border-border text-foreground max-h-36 overflow-x-auto rounded border p-2.5 font-mono text-xs leading-tight\">\n                {dryRunOutput}\n              </pre>\n            </div>\n          )}\n        </div>\n\n        <SheetFooter className=\"pt-2\">\n          <SheetClose asChild>\n            <Button variant=\"outline\" className=\"h-8.5 w-full text-xs sm:w-auto\">\n              Close Inspector\n            </Button>\n          </SheetClose>\n        </SheetFooter>\n      </SheetContent>\n    </Sheet>\n  )\n}\n",
      "type": "registry:page",
      "target": "~/components/blocks/McpToolInspectorDrawer.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/dialog.json",
    "https://uipkge.dev/r/react/dropdown-menu.json",
    "https://uipkge.dev/r/react/input.json",
    "https://uipkge.dev/r/react/separator.json",
    "https://uipkge.dev/r/react/sheet.json",
    "https://uipkge.dev/r/react/table.json",
    "https://uipkge.dev/r/react/tabs.json"
  ],
  "description": "Anthropic Model Context Protocol (MCP) server registry manager with connection health monitoring, stdio/SSE stream transport metrics, live tool schema explorer, parameterized resource URI templates, and JSON-RPC 2.0 payload inspection drawer.",
  "categories": [
    "ai",
    "app",
    "devops",
    "dashboard"
  ]
}