/** * Exposed tools card (mcp-ai-spec §6.2.4): live registry list grouped * read/write, annotations, collapsible parameter tables, anonymous-access * counts per access mode. */ import React, { useState } from 'react'; import { ChevronDown, ChevronUp } from 'lucide-react'; import type { McpStatus, McpToolInfo } from './types'; import { McpCard } from './card'; import { __, sprintf } from '../../lib/i18n'; export function ToolsList({ status }: { status: McpStatus }) { const readTools = status.tools.filter((t) => t.scope !== 'write'); const writeTools = status.tools.filter((t) => t.scope === 'write'); return ( {writeTools.length > 0 && (
)}
); } function ToolGroup({ heading, tools }: { heading: string; tools: McpToolInfo[] }) { return (

{heading}

); } function ToolRow({ tool }: { tool: McpToolInfo }) { const [open, setOpen] = useState(false); const params = tool.input_schema?.properties || {}; const paramNames = Object.keys(params); const required = tool.input_schema?.required || []; return (
  • {open && (
    {paramNames.length === 0 ? (

    {__('No parameters.', 'llmagnet-llm-txt-generator')}

    ) : ( {paramNames.map((name) => ( ))}
    {__('Parameter', 'llmagnet-llm-txt-generator')} {__('Type', 'llmagnet-llm-txt-generator')} {__('Description', 'llmagnet-llm-txt-generator')}
    {name} {required.includes(name) && ( * )} {params[name].type || '—'} {params[name].description || '—'}
    )}
    )}
  • ); } function ScopeBadge({ write }: { write: boolean }) { return ( {write ? __('Write', 'llmagnet-llm-txt-generator') : __('Read', 'llmagnet-llm-txt-generator')} ); } function AnnotationBadge({ children, tone = 'default', }: { children: React.ReactNode; tone?: 'default' | 'warning' | 'info' | 'plan'; }) { const tones: Record = { default: 'bg-gray-100 text-gray-600', warning: 'bg-red-100 text-red-700', info: 'bg-teal-50 text-teal-700', plan: 'bg-amber-100 text-amber-800', }; return ( {children} ); }