@visualsentinel/mcp-server 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +32 -7
- package/dist/api-client.d.ts +32 -0
- package/dist/api-client.js +79 -0
- package/dist/api-client.js.map +1 -0
- package/dist/index.js +227 -11
- package/dist/index.js.map +1 -1
- package/dist/tools.d.ts +38 -0
- package/dist/tools.js +546 -0
- package/dist/tools.js.map +1 -0
- package/package.json +14 -10
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api-client.ts","../src/tools.ts"],"sourcesContent":["/**\n * Visual Sentinel MCP server (stdio transport).\n *\n * Run via:\n * VS_API_KEY=vs_live_... npx @visualsentinel/mcp-server\n *\n * The server registers all tools defined in `./tools.ts` with the MCP SDK\n * and answers tools/list and tools/call requests. Public tools (health,\n * DNS check, SSL check, speed test, website check) work without an API key;\n * everything else returns a clear error if VS_API_KEY is not set.\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { ApiClient, VsApiError } from './api-client.js';\nimport { TOOLS, findTool } from './tools.js';\n\nconst SERVER_NAME = 'visualsentinel';\nconst SERVER_VERSION = '0.1.0';\n\nfunction toMcpToolDescriptor(tool: (typeof TOOLS)[number]) {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n };\n}\n\nasync function main(): Promise<void> {\n const client = new ApiClient();\n const server = new Server(\n { name: SERVER_NAME, version: SERVER_VERSION },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOLS.map(toMcpToolDescriptor),\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = findTool(req.params.name);\n if (!tool) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Unknown tool: ${req.params.name}` }],\n };\n }\n\n try {\n const result = await tool.handler(req.params.arguments ?? {}, client);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err) {\n const message = err instanceof VsApiError\n ? `Visual Sentinel API error (${err.status}): ${err.message}\\n${\n typeof err.body === 'string' ? err.body : JSON.stringify(err.body, null, 2)\n }`\n : err instanceof Error\n ? err.message\n : String(err);\n return {\n isError: true,\n content: [{ type: 'text', text: message }],\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error('[visualsentinel-mcp-server] fatal:', err);\n process.exit(1);\n});\n","/**\n * Tiny HTTP client for the Visual Sentinel public API.\n *\n * Reads the API key from `VS_API_KEY` (or `VISUALSENTINEL_API_KEY`) once at\n * construction time. All requests are routed at `https://visualsentinel.com`\n * unless `VS_API_BASE` overrides it (useful for testing against a local\n * dev instance).\n */\n\nconst DEFAULT_BASE = 'https://visualsentinel.com';\n\nexport interface ApiClientOptions {\n apiKey?: string | undefined;\n baseUrl?: string | undefined;\n userAgent?: string;\n}\n\nexport class VsApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: unknown,\n ) {\n super(message);\n this.name = 'VsApiError';\n }\n}\n\nexport class ApiClient {\n private readonly apiKey: string | undefined;\n private readonly baseUrl: string;\n private readonly userAgent: string;\n\n constructor(opts: ApiClientOptions = {}) {\n this.apiKey =\n opts.apiKey ??\n process.env.VS_API_KEY ??\n process.env.VISUALSENTINEL_API_KEY ??\n undefined;\n this.baseUrl = (opts.baseUrl ?? process.env.VS_API_BASE ?? DEFAULT_BASE).replace(\n /\\/+$/,\n '',\n );\n this.userAgent = opts.userAgent ?? '@visualsentinel/mcp-server';\n }\n\n hasApiKey(): boolean {\n return typeof this.apiKey === 'string' && this.apiKey.length > 0;\n }\n\n async request<T = unknown>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n options: { query?: Record<string, string | number | boolean | undefined>; body?: unknown; auth?: boolean } = {},\n ): Promise<T> {\n const auth = options.auth ?? true;\n if (auth && !this.hasApiKey()) {\n throw new VsApiError(\n 'Visual Sentinel API key required. Set VS_API_KEY (https://visualsentinel.com/settings/api-keys).',\n 401,\n null,\n );\n }\n\n const url = new URL(path.startsWith('/') ? path : `/${path}`, this.baseUrl);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': this.userAgent,\n };\n if (auth && this.apiKey) headers['X-API-Key'] = this.apiKey;\n if (options.body !== undefined) headers['Content-Type'] = 'application/json';\n\n const res = await fetch(url, {\n method,\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n });\n\n const text = await res.text();\n let parsed: unknown = null;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n throw new VsApiError(\n `Visual Sentinel API ${method} ${path} returned ${res.status}`,\n res.status,\n parsed,\n );\n }\n\n return parsed as T;\n }\n}\n","/**\n * Tool registry for the Visual Sentinel MCP server.\n *\n * Each tool wraps a single Visual Sentinel REST endpoint with a JSON Schema\n * input and a structured handler. Public-tool handlers (DNS check, SSL check,\n * speed test, website check, health) run without authentication; everything\n * else requires `VS_API_KEY`.\n */\n\nimport { ApiClient } from './api-client.js';\n\ninterface ToolInput {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n inputSchema: ToolInput;\n requiresAuth: boolean;\n handler: (args: Record<string, unknown>, client: ApiClient) => Promise<unknown>;\n}\n\nconst STR = { type: 'string' as const };\nconst NUM = { type: 'number' as const };\nconst INT = { type: 'integer' as const };\nconst BOOL = { type: 'boolean' as const };\n\nfunction pickString(args: Record<string, unknown>, key: string): string | undefined {\n const v = args[key];\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction pickNumber(args: Record<string, unknown>, key: string): number | undefined {\n const v = args[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined;\n}\n\nfunction requireString(args: Record<string, unknown>, key: string): string {\n const v = pickString(args, key);\n if (!v) throw new Error(`Argument \"${key}\" (string) is required.`);\n return v;\n}\n\nexport const TOOLS: ToolDefinition[] = [\n // -------------------------------------------------------------------------\n // Public tools (no auth)\n // -------------------------------------------------------------------------\n {\n name: 'vs_health',\n description:\n 'Check whether Visual Sentinel itself is up. Returns the service health status. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (_args, client) => client.request('GET', '/api/health', { auth: false }),\n },\n\n {\n name: 'vs_dns_check',\n description:\n 'Resolve DNS records (A, AAAA, MX, NS, TXT, CNAME) for a domain using Visual Sentinel\\'s public DNS lookup tool. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n domain: { ...STR, description: 'Domain to resolve, e.g. example.com (without protocol).' },\n recordType: {\n ...STR,\n description: 'Optional: limit to one record type. One of: A, AAAA, MX, NS, TXT, CNAME, SOA. Default: all.',\n },\n },\n required: ['domain'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/dns-check', {\n auth: false,\n query: {\n domain: requireString(args, 'domain'),\n recordType: pickString(args, 'recordType'),\n },\n }),\n },\n\n {\n name: 'vs_ssl_check',\n description:\n 'Inspect a TLS/SSL certificate for a hostname: issuer, subject, validity dates, SAN list, key algorithm, and certificate chain. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n host: { ...STR, description: 'Hostname to inspect, e.g. example.com (without protocol).' },\n port: { ...INT, description: 'TCP port. Default 443.' },\n },\n required: ['host'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/ssl-check', {\n auth: false,\n query: { host: requireString(args, 'host'), port: pickNumber(args, 'port') },\n }),\n },\n\n {\n name: 'vs_speed_test',\n description:\n 'Run a one-shot performance check against a URL: TTFB, total load time, transfer size, status code, and redirect chain. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n url: { ...STR, description: 'Full URL to test, including protocol (https://...).' },\n },\n required: ['url'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/speed-test', {\n auth: false,\n query: { url: requireString(args, 'url') },\n }),\n },\n\n {\n name: 'vs_website_check',\n description:\n 'Quick health check for a URL: HTTP status, response time, server header, content snippet, and basic SSL state. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n url: { ...STR, description: 'Full URL to test, including protocol (https://...).' },\n },\n required: ['url'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/website-check', {\n auth: false,\n query: { url: requireString(args, 'url') },\n }),\n },\n\n // -------------------------------------------------------------------------\n // Authenticated tools (require VS_API_KEY)\n // -------------------------------------------------------------------------\n {\n name: 'vs_monitors_list',\n description:\n 'List monitors in the authenticated organization. Optional filters narrow by status, type, or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'Filter: UP, DOWN, PAUSED, MAINTENANCE.' },\n type: {\n ...STR,\n description:\n 'Filter by monitor type: HTTP, HTTPS, KEYWORD, PING, PORT, DNS, SSL, VISUAL, CONTENT, API, GRAPHQL, WEBSOCKET.',\n },\n page: { ...INT, description: 'Page number (default 1).' },\n limit: { ...INT, description: 'Items per page (default 50, max 200).' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/monitors', {\n query: {\n status: pickString(args, 'status'),\n type: pickString(args, 'type'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_monitors_get',\n description:\n 'Fetch a single monitor by id, including its current status, last check, and configuration.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id (cuid).' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}`),\n },\n\n {\n name: 'vs_monitors_create',\n description:\n 'Create a new monitor. Provide at least name, url, and type. Returns the created monitor including its assigned id.',\n inputSchema: {\n type: 'object',\n properties: {\n name: { ...STR, description: 'Display name for the monitor.' },\n url: { ...STR, description: 'Full URL to monitor (or hostname for PING/PORT/DNS/SSL).' },\n type: {\n ...STR,\n description:\n 'Monitor type: HTTP, HTTPS, KEYWORD, PING, PORT, DNS, SSL, VISUAL, CONTENT, API, GRAPHQL, WEBSOCKET.',\n },\n interval: { ...INT, description: 'Check interval in seconds (60, 300, 600, 1800, 3600).' },\n timeout: { ...INT, description: 'Per-check timeout in seconds (default 30).' },\n method: { ...STR, description: 'HTTP method for HTTP/HTTPS monitors (default GET).' },\n keyword: { ...STR, description: 'Keyword to assert for KEYWORD monitors.' },\n port: { ...INT, description: 'TCP port for PORT monitors.' },\n },\n required: ['name', 'url', 'type'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', '/api/monitors', {\n body: {\n name: requireString(args, 'name'),\n url: requireString(args, 'url'),\n type: requireString(args, 'type'),\n interval: pickNumber(args, 'interval'),\n timeout: pickNumber(args, 'timeout'),\n method: pickString(args, 'method'),\n keyword: pickString(args, 'keyword'),\n port: pickNumber(args, 'port'),\n },\n }),\n },\n\n {\n name: 'vs_monitors_check_now',\n description:\n 'Trigger an immediate check for a monitor (in addition to its scheduled cadence). Returns the freshly-collected check result.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}/check`),\n },\n\n {\n name: 'vs_monitors_uptime',\n description:\n 'Fetch the uptime percentage and outage breakdown for a monitor over a window (default last 30 days).',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id.' },\n window: {\n ...STR,\n description: 'Window: 24h, 7d, 30d, 90d, 365d. Default 30d.',\n },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}/uptime`, {\n query: { window: pickString(args, 'window') },\n }),\n },\n\n {\n name: 'vs_incidents_list',\n description:\n 'List incidents for the authenticated organization. Filter by status (OPEN/RESOLVED), monitor id, or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'OPEN or RESOLVED.' },\n monitorId: { ...STR, description: 'Filter to one monitor.' },\n page: { ...INT },\n limit: { ...INT, description: 'Default 50, max 200.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/incidents', {\n query: {\n status: pickString(args, 'status'),\n monitorId: pickString(args, 'monitorId'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_incidents_get',\n description: 'Fetch a single incident with its full check history and root-cause hints.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Incident id.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', `/api/incidents/${encodeURIComponent(requireString(args, 'id'))}`),\n },\n\n {\n name: 'vs_alerts_list',\n description:\n 'List alerts for the authenticated organization. Filter by status (UNACKNOWLEDGED/ACKNOWLEDGED/RESOLVED) or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'UNACKNOWLEDGED, ACKNOWLEDGED, or RESOLVED.' },\n page: { ...INT },\n limit: { ...INT, description: 'Default 50, max 200.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/alerts', {\n query: {\n status: pickString(args, 'status'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_alerts_acknowledge',\n description: 'Acknowledge an alert by id. Acknowledgement is recorded with the calling API key\\'s user.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Alert id.' },\n note: { ...STR, description: 'Optional acknowledgement note (visible in alert history).' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', `/api/alerts/${encodeURIComponent(requireString(args, 'id'))}/acknowledge`, {\n body: { note: pickString(args, 'note') },\n }),\n },\n\n {\n name: 'vs_status_pages_list',\n description: 'List public-facing status pages owned by the authenticated organization.',\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (_args, client) => client.request('GET', '/api/status-pages'),\n },\n\n {\n name: 'vs_servers_list',\n description: 'List servers (origins) registered in the authenticated organization.',\n inputSchema: {\n type: 'object',\n properties: {\n page: { ...INT },\n limit: { ...INT, description: 'Default 50.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/servers', {\n query: { page: pickNumber(args, 'page'), limit: pickNumber(args, 'limit') },\n }),\n },\n];\n\nexport function findTool(name: string): ToolDefinition | undefined {\n return TOOLS.find((t) => t.name === name);\n}\n\n// Suppress unused-warning suppression: BOOL/NUM are reserved for future tools.\nvoid BOOL;\nvoid NUM;\n"],"mappings":";;;AAYA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACRP,IAAM,eAAe;AAQd,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACgB,QACA,MAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;AAEO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,OAAyB,CAAC,GAAG;AACvC,SAAK,SACH,KAAK,UACL,QAAQ,IAAI,cACZ,QAAQ,IAAI,0BACZ;AACF,SAAK,WAAW,KAAK,WAAW,QAAQ,IAAI,eAAe,cAAc;AAAA,MACvE;AAAA,MACA;AAAA,IACF;AACA,SAAK,YAAY,KAAK,aAAa;AAAA,EACrC;AAAA,EAEA,YAAqB;AACnB,WAAO,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,SAAS;AAAA,EACjE;AAAA,EAEA,MAAM,QACJ,QACA,MACA,UAA6G,CAAC,GAClG;AACZ,UAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAI,QAAQ,CAAC,KAAK,UAAU,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,IAAI,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,OAAO;AAC1E,QAAI,QAAQ,OAAO;AACjB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AAClD,YAAI,MAAM,UAAa,MAAM,KAAM,KAAI,aAAa,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,MACtE;AAAA,IACF;AAEA,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MACR,cAAc,KAAK;AAAA,IACrB;AACA,QAAI,QAAQ,KAAK,OAAQ,SAAQ,WAAW,IAAI,KAAK;AACrD,QAAI,QAAQ,SAAS,OAAW,SAAQ,cAAc,IAAI;AAE1D,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,IACpE,CAAC;AAED,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,SAAkB;AACtB,QAAI,KAAK,SAAS,GAAG;AACnB,UAAI;AACF,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,QAAQ;AACN,iBAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR,uBAAuB,MAAM,IAAI,IAAI,aAAa,IAAI,MAAM;AAAA,QAC5D,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AC9EA,IAAM,MAAM,EAAE,MAAM,SAAkB;AAEtC,IAAM,MAAM,EAAE,MAAM,UAAmB;AAGvC,SAAS,WAAW,MAA+B,KAAiC;AAClF,QAAM,IAAI,KAAK,GAAG;AAClB,SAAO,OAAO,MAAM,YAAY,EAAE,SAAS,IAAI,IAAI;AACrD;AAEA,SAAS,WAAW,MAA+B,KAAiC;AAClF,QAAM,IAAI,KAAK,GAAG;AAClB,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D;AAEA,SAAS,cAAc,MAA+B,KAAqB;AACzE,QAAM,IAAI,WAAW,MAAM,GAAG;AAC9B,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,aAAa,GAAG,yBAAyB;AACjE,SAAO;AACT;AAEO,IAAM,QAA0B;AAAA;AAAA;AAAA;AAAA,EAIrC;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,OAAO,WAAW,OAAO,QAAQ,OAAO,eAAe,EAAE,MAAM,MAAM,CAAC;AAAA,EACxF;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,0DAA0D;AAAA,QACzF,YAAY;AAAA,UACV,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,MACnB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,wBAAwB;AAAA,MAC5C,MAAM;AAAA,MACN,OAAO;AAAA,QACL,QAAQ,cAAc,MAAM,QAAQ;AAAA,QACpC,YAAY,WAAW,MAAM,YAAY;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,GAAG,KAAK,aAAa,4DAA4D;AAAA,QACzF,MAAM,EAAE,GAAG,KAAK,aAAa,yBAAyB;AAAA,MACxD;AAAA,MACA,UAAU,CAAC,MAAM;AAAA,MACjB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,wBAAwB;AAAA,MAC5C,MAAM;AAAA,MACN,OAAO,EAAE,MAAM,cAAc,MAAM,MAAM,GAAG,MAAM,WAAW,MAAM,MAAM,EAAE;AAAA,IAC7E,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK,EAAE,GAAG,KAAK,aAAa,sDAAsD;AAAA,MACpF;AAAA,MACA,UAAU,CAAC,KAAK;AAAA,MAChB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,yBAAyB;AAAA,MAC7C,MAAM;AAAA,MACN,OAAO,EAAE,KAAK,cAAc,MAAM,KAAK,EAAE;AAAA,IAC3C,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK,EAAE,GAAG,KAAK,aAAa,sDAAsD;AAAA,MACpF;AAAA,MACA,UAAU,CAAC,KAAK;AAAA,MAChB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,4BAA4B;AAAA,MAChD,MAAM;AAAA,MACN,OAAO,EAAE,KAAK,cAAc,MAAM,KAAK,EAAE;AAAA,IAC3C,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,yCAAyC;AAAA,QACxE,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aACE;AAAA,QACJ;AAAA,QACA,MAAM,EAAE,GAAG,KAAK,aAAa,2BAA2B;AAAA,QACxD,OAAO,EAAE,GAAG,KAAK,aAAa,wCAAwC;AAAA,MACxE;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,iBAAiB;AAAA,MACrC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,qBAAqB;AAAA,MAClD;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,EAAE;AAAA,EAC1F;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,GAAG,KAAK,aAAa,gCAAgC;AAAA,QAC7D,KAAK,EAAE,GAAG,KAAK,aAAa,2DAA2D;AAAA,QACvF,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aACE;AAAA,QACJ;AAAA,QACA,UAAU,EAAE,GAAG,KAAK,aAAa,wDAAwD;AAAA,QACzF,SAAS,EAAE,GAAG,KAAK,aAAa,6CAA6C;AAAA,QAC7E,QAAQ,EAAE,GAAG,KAAK,aAAa,qDAAqD;AAAA,QACpF,SAAS,EAAE,GAAG,KAAK,aAAa,0CAA0C;AAAA,QAC1E,MAAM,EAAE,GAAG,KAAK,aAAa,8BAA8B;AAAA,MAC7D;AAAA,MACA,UAAU,CAAC,QAAQ,OAAO,MAAM;AAAA,MAChC,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,iBAAiB;AAAA,MACtC,MAAM;AAAA,QACJ,MAAM,cAAc,MAAM,MAAM;AAAA,QAChC,KAAK,cAAc,MAAM,KAAK;AAAA,QAC9B,MAAM,cAAc,MAAM,MAAM;AAAA,QAChC,UAAU,WAAW,MAAM,UAAU;AAAA,QACrC,SAAS,WAAW,MAAM,SAAS;AAAA,QACnC,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,SAAS,WAAW,MAAM,SAAS;AAAA,QACnC,MAAM,WAAW,MAAM,MAAM;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,MAC3C;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,QAAQ;AAAA,EACjG;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,QACzC,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,WAAW;AAAA,MAC7F,OAAO,EAAE,QAAQ,WAAW,MAAM,QAAQ,EAAE;AAAA,IAC9C,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,oBAAoB;AAAA,QACnD,WAAW,EAAE,GAAG,KAAK,aAAa,yBAAyB;AAAA,QAC3D,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,uBAAuB;AAAA,MACvD;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,kBAAkB;AAAA,MACtC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,WAAW,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,eAAe;AAAA,MAC5C;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,kBAAkB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,EAAE;AAAA,EAC3F;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,6CAA6C;AAAA,QAC5E,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,uBAAuB;AAAA,MACvD;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,eAAe;AAAA,MACnC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,YAAY;AAAA,QACvC,MAAM,EAAE,GAAG,KAAK,aAAa,4DAA4D;AAAA,MAC3F;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,eAAe,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,gBAAgB;AAAA,MACjG,MAAM,EAAE,MAAM,WAAW,MAAM,MAAM,EAAE;AAAA,IACzC,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,OAAO,WAAW,OAAO,QAAQ,OAAO,mBAAmB;AAAA,EAC7E;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,MAC9C;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,gBAAgB;AAAA,MACpC,OAAO,EAAE,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,WAAW,MAAM,OAAO,EAAE;AAAA,IAC5E,CAAC;AAAA,EACL;AACF;AAEO,SAAS,SAAS,MAA0C;AACjE,SAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC1C;;;AFzXA,IAAM,cAAc;AACpB,IAAM,iBAAiB;AAEvB,SAAS,oBAAoB,MAA8B;AACzD,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,aAAa,KAAK;AAAA,EACpB;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,aAAa,SAAS,eAAe;AAAA,IAC7C,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO,kBAAkB,wBAAwB,aAAa;AAAA,IAC5D,OAAO,MAAM,IAAI,mBAAmB;AAAA,EACtC,EAAE;AAEF,SAAO,kBAAkB,uBAAuB,OAAO,QAAQ;AAC7D,UAAM,OAAO,SAAS,IAAI,OAAO,IAAI;AACrC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,OAAO,IAAI,GAAG,CAAC;AAAA,MACtE;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAAQ,IAAI,OAAO,aAAa,CAAC,GAAG,MAAM;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,aAC3B,8BAA8B,IAAI,MAAM,MAAM,IAAI,OAAO;AAAA,EACvD,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,KAAK,UAAU,IAAI,MAAM,MAAM,CAAC,CAC5E,KACA,eAAe,QACb,IAAI,UACJ,OAAO,GAAG;AAChB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AAEpB,UAAQ,MAAM,sCAAsC,GAAG;AACvD,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api-client.ts","../src/tools.ts"],"sourcesContent":["/**\n * Visual Sentinel MCP server (stdio transport).\n *\n * Run via:\n * VS_API_KEY=vs_live_... npx @visualsentinel/mcp-server\n *\n * The server registers all tools defined in `./tools.ts` with the MCP SDK\n * and answers tools/list and tools/call requests. Public tools (health,\n * DNS check, SSL check, speed test, website check) work without an API key;\n * everything else returns a clear error if VS_API_KEY is not set.\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { ApiClient, VsApiError } from './api-client.js';\nimport { TOOLS, findTool } from './tools.js';\n\nconst SERVER_NAME = 'visualsentinel';\nconst SERVER_VERSION = '0.2.1';\n\nfunction toMcpToolDescriptor(tool: (typeof TOOLS)[number]) {\n return {\n name: tool.name,\n title: tool.title,\n description: tool.description,\n annotations: tool.annotations,\n inputSchema: tool.inputSchema,\n };\n}\n\nasync function main(): Promise<void> {\n const client = new ApiClient();\n const server = new Server(\n { name: SERVER_NAME, version: SERVER_VERSION },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOLS.map(toMcpToolDescriptor),\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = findTool(req.params.name);\n if (!tool) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Unknown tool: ${req.params.name}` }],\n };\n }\n\n try {\n const result = await tool.handler(req.params.arguments ?? {}, client);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err) {\n const message = err instanceof VsApiError\n ? `Visual Sentinel API error (${err.status}): ${err.message}\\n${\n typeof err.body === 'string' ? err.body : JSON.stringify(err.body, null, 2)\n }`\n : err instanceof Error\n ? err.message\n : String(err);\n return {\n isError: true,\n content: [{ type: 'text', text: message }],\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error('[visualsentinel-mcp-server] fatal:', err);\n process.exit(1);\n});\n","/**\n * Tiny HTTP client for the Visual Sentinel public API.\n *\n * Reads the API key from `VS_API_KEY` (or `VISUALSENTINEL_API_KEY`) once at\n * construction time. All requests are routed at `https://visualsentinel.com`\n * unless `VS_API_BASE` overrides it (useful for testing against a local\n * dev instance).\n */\n\nconst DEFAULT_BASE = 'https://visualsentinel.com';\n\nexport interface ApiClientOptions {\n apiKey?: string | undefined;\n baseUrl?: string | undefined;\n userAgent?: string;\n}\n\nexport class VsApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: unknown,\n ) {\n super(message);\n this.name = 'VsApiError';\n }\n}\n\nexport class ApiClient {\n private readonly apiKey: string | undefined;\n private readonly baseUrl: string;\n private readonly userAgent: string;\n\n constructor(opts: ApiClientOptions = {}) {\n this.apiKey =\n opts.apiKey ??\n process.env.VS_API_KEY ??\n process.env.VISUALSENTINEL_API_KEY ??\n undefined;\n this.baseUrl = (opts.baseUrl ?? process.env.VS_API_BASE ?? DEFAULT_BASE).replace(\n /\\/+$/,\n '',\n );\n this.userAgent = opts.userAgent ?? '@visualsentinel/mcp-server';\n }\n\n hasApiKey(): boolean {\n return typeof this.apiKey === 'string' && this.apiKey.length > 0;\n }\n\n async request<T = unknown>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n options: { query?: Record<string, string | number | boolean | undefined>; body?: unknown; auth?: boolean } = {},\n ): Promise<T> {\n const auth = options.auth ?? true;\n if (auth && !this.hasApiKey()) {\n throw new VsApiError(\n 'Visual Sentinel API key required. Set VS_API_KEY (https://visualsentinel.com/settings/api-keys).',\n 401,\n null,\n );\n }\n\n const url = new URL(path.startsWith('/') ? path : `/${path}`, this.baseUrl);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': this.userAgent,\n };\n if (auth && this.apiKey) headers['X-API-Key'] = this.apiKey;\n if (options.body !== undefined) headers['Content-Type'] = 'application/json';\n\n const res = await fetch(url, {\n method,\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n });\n\n const text = await res.text();\n let parsed: unknown = null;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n throw new VsApiError(\n `Visual Sentinel API ${method} ${path} returned ${res.status}`,\n res.status,\n parsed,\n );\n }\n\n return parsed as T;\n }\n}\n","/**\n * Tool registry for the Visual Sentinel MCP server.\n *\n * Each tool wraps a single Visual Sentinel REST endpoint with a JSON Schema\n * input and a structured handler. Public-tool handlers (DNS check, SSL check,\n * speed test, website check, health) run without authentication; everything\n * else requires `VS_API_KEY`.\n */\n\nimport { ApiClient } from './api-client.js';\n\ninterface ToolInput {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n}\n\nexport interface ToolAnnotations {\n title: string;\n readOnlyHint: boolean;\n destructiveHint: boolean;\n idempotentHint: boolean;\n openWorldHint: boolean;\n}\n\nexport interface ToolDefinition {\n name: string;\n /** Human-readable title shown by MCP clients. */\n title: string;\n description: string;\n annotations: ToolAnnotations;\n inputSchema: ToolInput;\n requiresAuth: boolean;\n handler: (args: Record<string, unknown>, client: ApiClient) => Promise<unknown>;\n}\n\nconst STR = { type: 'string' as const };\nconst NUM = { type: 'number' as const };\nconst INT = { type: 'integer' as const };\nconst BOOL = { type: 'boolean' as const };\n\nfunction pickString(args: Record<string, unknown>, key: string): string | undefined {\n const v = args[key];\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction pickNumber(args: Record<string, unknown>, key: string): number | undefined {\n const v = args[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined;\n}\n\nfunction requireString(args: Record<string, unknown>, key: string): string {\n const v = pickString(args, key);\n if (!v) throw new Error(`Argument \"${key}\" (string) is required.`);\n return v;\n}\n\nexport const TOOLS: ToolDefinition[] = [\n // -------------------------------------------------------------------------\n // Public tools (no auth)\n // -------------------------------------------------------------------------\n {\n name: 'vs_health',\n title: 'Check Visual Sentinel service health',\n annotations: {\n title: 'Check Visual Sentinel service health',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n description:\n 'Check whether Visual Sentinel itself is up. Returns the service health status. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (_args, client) => client.request('GET', '/api/health', { auth: false }),\n },\n\n {\n name: 'vs_dns_check',\n title: 'Look up DNS records',\n annotations: {\n title: 'Look up DNS records',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n description:\n 'Resolve DNS records (A, AAAA, MX, NS, TXT, CNAME) for a domain using Visual Sentinel\\'s public DNS lookup tool. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n domain: { ...STR, description: 'Domain to resolve, e.g. example.com (without protocol).' },\n recordType: {\n ...STR,\n description: 'Optional: limit to one record type. One of: A, AAAA, MX, NS, TXT, CNAME, SOA. Default: all.',\n },\n },\n required: ['domain'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/dns-check', {\n auth: false,\n query: {\n domain: requireString(args, 'domain'),\n // The API reads ?type= (not recordType).\n type: pickString(args, 'recordType'),\n },\n }),\n },\n\n {\n name: 'vs_ssl_check',\n title: 'Inspect an SSL certificate',\n annotations: {\n title: 'Inspect an SSL certificate',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n description:\n 'Inspect a TLS/SSL certificate for a hostname: issuer, subject, validity dates, SAN list, key algorithm, and certificate chain. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n domain: { ...STR, description: 'Hostname to inspect, e.g. example.com (without protocol).' },\n },\n required: ['domain'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/ssl-check', {\n auth: false,\n // The API reads ?domain=. `host` stays as an input alias for 0.1.x callers.\n query: { domain: pickString(args, 'domain') ?? requireString(args, 'host') },\n }),\n },\n\n {\n name: 'vs_speed_test',\n title: 'Run a one-shot speed test',\n annotations: {\n title: 'Run a one-shot speed test',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n description:\n 'Run a one-shot performance check against a URL: TTFB, total load time, transfer size, status code, and redirect chain. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n url: { ...STR, description: 'Full URL to test, including protocol (https://...).' },\n },\n required: ['url'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/speed-test', {\n auth: false,\n query: { url: requireString(args, 'url') },\n }),\n },\n\n {\n name: 'vs_website_check',\n title: 'Check a website',\n annotations: {\n title: 'Check a website',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n description:\n 'Quick health check for a URL: HTTP status, response time, server header, content snippet, and basic SSL state. No authentication required.',\n inputSchema: {\n type: 'object',\n properties: {\n url: { ...STR, description: 'Full URL to test, including protocol (https://...).' },\n },\n required: ['url'],\n additionalProperties: false,\n },\n requiresAuth: false,\n handler: async (args, client) =>\n client.request('GET', '/api/tools/website-check', {\n auth: false,\n query: { url: requireString(args, 'url') },\n }),\n },\n\n // -------------------------------------------------------------------------\n // Authenticated tools (require VS_API_KEY)\n // -------------------------------------------------------------------------\n {\n name: 'vs_monitors_list',\n title: 'List monitors',\n annotations: {\n title: 'List monitors',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'List monitors in the authenticated organization. Optional filters narrow by status, type, or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'Filter: UP, DOWN, PAUSED, MAINTENANCE.' },\n type: {\n ...STR,\n description:\n 'Filter by monitor type: HTTP, HTTPS, KEYWORD, PING, PORT, DNS, SSL, VISUAL, CONTENT, API, GRAPHQL, WEBSOCKET.',\n },\n page: { ...INT, description: 'Page number (default 1).' },\n limit: { ...INT, description: 'Items per page (default 50, max 200).' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/monitors', {\n query: {\n status: pickString(args, 'status'),\n type: pickString(args, 'type'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_monitors_get',\n title: 'Get a monitor',\n annotations: {\n title: 'Get a monitor',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'Fetch a single monitor by id, including its current status, last check, and configuration.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id (cuid).' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}`),\n },\n\n {\n name: 'vs_monitors_create',\n title: 'Create a monitor',\n annotations: {\n title: 'Create a monitor',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n description:\n 'Create a new monitor. Provide at least name, url, and type. Returns the created monitor including its assigned id.',\n inputSchema: {\n type: 'object',\n properties: {\n name: { ...STR, description: 'Display name for the monitor.' },\n url: { ...STR, description: 'Full URL to monitor (or hostname for PING/PORT/DNS/SSL).' },\n type: {\n ...STR,\n description:\n 'Monitor type: HTTP, HTTPS, KEYWORD, PING, PORT, DNS, SSL, VISUAL, CONTENT, API, GRAPHQL, WEBSOCKET.',\n },\n interval: { ...INT, description: 'Check interval in seconds (60, 300, 600, 1800, 3600).' },\n timeout: { ...INT, description: 'Per-check timeout in seconds (default 30).' },\n method: { ...STR, description: 'HTTP method for HTTP/HTTPS monitors (default GET).' },\n keyword: { ...STR, description: 'Keyword to assert for KEYWORD monitors.' },\n port: { ...INT, description: 'TCP port for PORT monitors.' },\n },\n required: ['name', 'url', 'type'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', '/api/monitors', {\n body: {\n name: requireString(args, 'name'),\n url: requireString(args, 'url'),\n type: requireString(args, 'type'),\n interval: pickNumber(args, 'interval'),\n timeout: pickNumber(args, 'timeout'),\n method: pickString(args, 'method'),\n keyword: pickString(args, 'keyword'),\n port: pickNumber(args, 'port'),\n },\n }),\n },\n\n {\n name: 'vs_monitors_check_now',\n title: 'Run a monitor check now',\n annotations: {\n title: 'Run a monitor check now',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n description:\n 'Trigger an immediate check for a monitor (in addition to its scheduled cadence). Returns the freshly-collected check result.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}/check`),\n },\n\n {\n name: 'vs_monitors_uptime',\n title: 'Get monitor uptime',\n annotations: {\n title: 'Get monitor uptime',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'Fetch the uptime percentage and time-series breakdown for a monitor. Use `window` for a preset window (24h, 7d, 30d, 90d, 365d; default 30d), supply both `from` and `to` (ISO 8601) for a custom date range, or set `all: true` for the full available history.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Monitor id.' },\n window: {\n ...STR,\n description: 'Preset window: 1h, 6h, 24h, 7d, 30d, 90d, 365d. Default 30d. Ignored when from+to or all are supplied.',\n },\n from: {\n ...STR,\n description: 'ISO 8601 start of a custom range (e.g. 2026-01-01T00:00:00Z). Must be supplied with `to`.',\n },\n to: {\n ...STR,\n description: 'ISO 8601 end of a custom range. Must be supplied with `from`.',\n },\n all: {\n type: 'boolean',\n description: 'Return the full available history from the earliest stored data. Takes precedence over from/to and window.',\n },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) => {\n const from = pickString(args, 'from');\n const to = pickString(args, 'to');\n // Precedence mirrors the API: all > from/to > window/period.\n const query = args['all'] === true\n ? { all: true }\n : (from && to)\n ? { from, to }\n : { period: pickString(args, 'window') ?? '30d' };\n return client.request(\n 'GET',\n `/api/monitors/${encodeURIComponent(requireString(args, 'id'))}/uptime`,\n { query },\n );\n },\n },\n\n {\n name: 'vs_monitors_metrics_bulk',\n title: 'Get bulk monitor metrics',\n annotations: {\n title: 'Get bulk monitor metrics',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'Fetch uptime or response-time metrics for up to 100 monitors in a single request. Use `window` for a preset window (1h, 6h, 24h, 7d, 30d, 90d, 365d; default 30d), supply both `from` and `to` (ISO 8601) for a custom date range, or set `all: true` for the full available history. Returns a `monitors` object keyed by monitor id.',\n inputSchema: {\n type: 'object',\n properties: {\n monitorIds: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of monitor IDs to fetch metrics for (max 100).',\n },\n metric: {\n ...STR,\n description: 'Metric to return: \"uptime\" or \"response-time\".',\n },\n window: {\n ...STR,\n description: 'Preset window: 1h, 6h, 24h, 7d, 30d, 90d, 365d. Default 30d. Ignored when from+to or all are supplied.',\n },\n from: {\n ...STR,\n description: 'ISO 8601 start of a custom range (e.g. 2026-01-01T00:00:00Z). Must be supplied with `to`.',\n },\n to: {\n ...STR,\n description: 'ISO 8601 end of a custom range. Must be supplied with `from`.',\n },\n all: {\n type: 'boolean',\n description: 'Return the full available history from the earliest stored data. Takes precedence over from/to and window.',\n },\n },\n required: ['monitorIds', 'metric'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) => {\n const monitorIds = args['monitorIds'];\n if (!Array.isArray(monitorIds) || monitorIds.length === 0) {\n throw new Error('Argument \"monitorIds\" must be a non-empty array.');\n }\n const from = pickString(args, 'from');\n const to = pickString(args, 'to');\n const body: Record<string, unknown> = {\n monitorIds,\n metric: requireString(args, 'metric'),\n };\n // Precedence mirrors the API: all > from/to > window/period.\n if (args['all'] === true) {\n body['all'] = true;\n } else if (from && to) {\n body['from'] = from;\n body['to'] = to;\n } else {\n body['period'] = pickString(args, 'window') ?? '30d';\n }\n return client.request('POST', '/api/monitors/metrics', { body });\n },\n },\n\n {\n name: 'vs_incidents_list',\n title: 'List incidents',\n annotations: {\n title: 'List incidents',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'List incidents for the authenticated organization. Filter by status (OPEN/RESOLVED), monitor id, or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'OPEN or RESOLVED.' },\n monitorId: { ...STR, description: 'Filter to one monitor.' },\n page: { ...INT },\n limit: { ...INT, description: 'Default 50, max 200.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/incidents', {\n query: {\n status: pickString(args, 'status'),\n monitorId: pickString(args, 'monitorId'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_incidents_get',\n title: 'Get an incident',\n annotations: {\n title: 'Get an incident',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description: 'Fetch a single incident with its full check history and root-cause hints.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Incident id.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', `/api/incidents/${encodeURIComponent(requireString(args, 'id'))}`),\n },\n\n {\n name: 'vs_alerts_list',\n title: 'List alerts',\n annotations: {\n title: 'List alerts',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description:\n 'List alerts for the authenticated organization. Filter by status (UNACKNOWLEDGED/ACKNOWLEDGED/RESOLVED) or paginate.',\n inputSchema: {\n type: 'object',\n properties: {\n status: { ...STR, description: 'UNACKNOWLEDGED, ACKNOWLEDGED, or RESOLVED.' },\n page: { ...INT },\n limit: { ...INT, description: 'Default 50, max 200.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/alerts', {\n query: {\n status: pickString(args, 'status'),\n page: pickNumber(args, 'page'),\n limit: pickNumber(args, 'limit'),\n },\n }),\n },\n\n {\n name: 'vs_alerts_acknowledge',\n title: 'Acknowledge an alert',\n annotations: {\n title: 'Acknowledge an alert',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description: 'Acknowledge an alert by id. Acknowledgement is recorded with the calling API key\\'s user.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { ...STR, description: 'Alert id.' },\n note: { ...STR, description: 'Optional acknowledgement note (visible in alert history).' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('POST', `/api/alerts/${encodeURIComponent(requireString(args, 'id'))}/acknowledge`, {\n body: { note: pickString(args, 'note') },\n }),\n },\n\n {\n name: 'vs_status_pages_list',\n title: 'List status pages',\n annotations: {\n title: 'List status pages',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description: 'List public-facing status pages owned by the authenticated organization.',\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (_args, client) => client.request('GET', '/api/status-pages'),\n },\n\n {\n name: 'vs_servers_list',\n title: 'List servers',\n annotations: {\n title: 'List servers',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n description: 'List servers (origins) registered in the authenticated organization.',\n inputSchema: {\n type: 'object',\n properties: {\n page: { ...INT },\n limit: { ...INT, description: 'Default 50.' },\n },\n additionalProperties: false,\n },\n requiresAuth: true,\n handler: async (args, client) =>\n client.request('GET', '/api/servers', {\n query: { page: pickNumber(args, 'page'), limit: pickNumber(args, 'limit') },\n }),\n },\n];\n\nexport function findTool(name: string): ToolDefinition | undefined {\n return TOOLS.find((t) => t.name === name);\n}\n\n// Suppress unused-warning suppression: BOOL/NUM are reserved for future tools.\nvoid BOOL;\nvoid NUM;\n"],"mappings":";;;AAYA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACRP,IAAM,eAAe;AAQd,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACgB,QACA,MAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;AAEO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,OAAyB,CAAC,GAAG;AACvC,SAAK,SACH,KAAK,UACL,QAAQ,IAAI,cACZ,QAAQ,IAAI,0BACZ;AACF,SAAK,WAAW,KAAK,WAAW,QAAQ,IAAI,eAAe,cAAc;AAAA,MACvE;AAAA,MACA;AAAA,IACF;AACA,SAAK,YAAY,KAAK,aAAa;AAAA,EACrC;AAAA,EAEA,YAAqB;AACnB,WAAO,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,SAAS;AAAA,EACjE;AAAA,EAEA,MAAM,QACJ,QACA,MACA,UAA6G,CAAC,GAClG;AACZ,UAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAI,QAAQ,CAAC,KAAK,UAAU,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,IAAI,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,OAAO;AAC1E,QAAI,QAAQ,OAAO;AACjB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AAClD,YAAI,MAAM,UAAa,MAAM,KAAM,KAAI,aAAa,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,MACtE;AAAA,IACF;AAEA,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MACR,cAAc,KAAK;AAAA,IACrB;AACA,QAAI,QAAQ,KAAK,OAAQ,SAAQ,WAAW,IAAI,KAAK;AACrD,QAAI,QAAQ,SAAS,OAAW,SAAQ,cAAc,IAAI;AAE1D,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,IACpE,CAAC;AAED,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,SAAkB;AACtB,QAAI,KAAK,SAAS,GAAG;AACnB,UAAI;AACF,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,QAAQ;AACN,iBAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR,uBAAuB,MAAM,IAAI,IAAI,aAAa,IAAI,MAAM;AAAA,QAC5D,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACnEA,IAAM,MAAM,EAAE,MAAM,SAAkB;AAEtC,IAAM,MAAM,EAAE,MAAM,UAAmB;AAGvC,SAAS,WAAW,MAA+B,KAAiC;AAClF,QAAM,IAAI,KAAK,GAAG;AAClB,SAAO,OAAO,MAAM,YAAY,EAAE,SAAS,IAAI,IAAI;AACrD;AAEA,SAAS,WAAW,MAA+B,KAAiC;AAClF,QAAM,IAAI,KAAK,GAAG;AAClB,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D;AAEA,SAAS,cAAc,MAA+B,KAAqB;AACzE,QAAM,IAAI,WAAW,MAAM,GAAG;AAC9B,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,aAAa,GAAG,yBAAyB;AACjE,SAAO;AACT;AAEO,IAAM,QAA0B;AAAA;AAAA;AAAA;AAAA,EAIrC;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,OAAO,WAAW,OAAO,QAAQ,OAAO,eAAe,EAAE,MAAM,MAAM,CAAC;AAAA,EACxF;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,0DAA0D;AAAA,QACzF,YAAY;AAAA,UACV,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,MACnB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,wBAAwB;AAAA,MAC5C,MAAM;AAAA,MACN,OAAO;AAAA,QACL,QAAQ,cAAc,MAAM,QAAQ;AAAA;AAAA,QAEpC,MAAM,WAAW,MAAM,YAAY;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,4DAA4D;AAAA,MAC7F;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,MACnB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,wBAAwB;AAAA,MAC5C,MAAM;AAAA;AAAA,MAEN,OAAO,EAAE,QAAQ,WAAW,MAAM,QAAQ,KAAK,cAAc,MAAM,MAAM,EAAE;AAAA,IAC7E,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK,EAAE,GAAG,KAAK,aAAa,sDAAsD;AAAA,MACpF;AAAA,MACA,UAAU,CAAC,KAAK;AAAA,MAChB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,yBAAyB;AAAA,MAC7C,MAAM;AAAA,MACN,OAAO,EAAE,KAAK,cAAc,MAAM,KAAK,EAAE;AAAA,IAC3C,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK,EAAE,GAAG,KAAK,aAAa,sDAAsD;AAAA,MACpF;AAAA,MACA,UAAU,CAAC,KAAK;AAAA,MAChB,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,4BAA4B;AAAA,MAChD,MAAM;AAAA,MACN,OAAO,EAAE,KAAK,cAAc,MAAM,KAAK,EAAE;AAAA,IAC3C,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,yCAAyC;AAAA,QACxE,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aACE;AAAA,QACJ;AAAA,QACA,MAAM,EAAE,GAAG,KAAK,aAAa,2BAA2B;AAAA,QACxD,OAAO,EAAE,GAAG,KAAK,aAAa,wCAAwC;AAAA,MACxE;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,iBAAiB;AAAA,MACrC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,qBAAqB;AAAA,MAClD;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,EAAE;AAAA,EAC1F;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,GAAG,KAAK,aAAa,gCAAgC;AAAA,QAC7D,KAAK,EAAE,GAAG,KAAK,aAAa,2DAA2D;AAAA,QACvF,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aACE;AAAA,QACJ;AAAA,QACA,UAAU,EAAE,GAAG,KAAK,aAAa,wDAAwD;AAAA,QACzF,SAAS,EAAE,GAAG,KAAK,aAAa,6CAA6C;AAAA,QAC7E,QAAQ,EAAE,GAAG,KAAK,aAAa,qDAAqD;AAAA,QACpF,SAAS,EAAE,GAAG,KAAK,aAAa,0CAA0C;AAAA,QAC1E,MAAM,EAAE,GAAG,KAAK,aAAa,8BAA8B;AAAA,MAC7D;AAAA,MACA,UAAU,CAAC,QAAQ,OAAO,MAAM;AAAA,MAChC,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,iBAAiB;AAAA,MACtC,MAAM;AAAA,QACJ,MAAM,cAAc,MAAM,MAAM;AAAA,QAChC,KAAK,cAAc,MAAM,KAAK;AAAA,QAC9B,MAAM,cAAc,MAAM,MAAM;AAAA,QAChC,UAAU,WAAW,MAAM,UAAU;AAAA,QACrC,SAAS,WAAW,MAAM,SAAS;AAAA,QACnC,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,SAAS,WAAW,MAAM,SAAS;AAAA,QACnC,MAAM,WAAW,MAAM,MAAM;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,MAC3C;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,QAAQ;AAAA,EACjG;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,QACzC,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,IAAI;AAAA,UACF,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,KAAK;AAAA,UACH,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WAAW;AAC/B,YAAM,OAAO,WAAW,MAAM,MAAM;AACpC,YAAM,KAAK,WAAW,MAAM,IAAI;AAEhC,YAAM,QAAQ,KAAK,KAAK,MAAM,OAC1B,EAAE,KAAK,KAAK,IACX,QAAQ,KACP,EAAE,MAAM,GAAG,IACX,EAAE,QAAQ,WAAW,MAAM,QAAQ,KAAK,MAAM;AACpD,aAAO,OAAO;AAAA,QACZ;AAAA,QACA,iBAAiB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC;AAAA,QAC9D,EAAE,MAAM;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,YAAY;AAAA,UACV,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,SAAS;AAAA,UACxB,aAAa;AAAA,QACf;AAAA,QACA,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,IAAI;AAAA,UACF,GAAG;AAAA,UACH,aAAa;AAAA,QACf;AAAA,QACA,KAAK;AAAA,UACH,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,cAAc,QAAQ;AAAA,MACjC,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WAAW;AAC/B,YAAM,aAAa,KAAK,YAAY;AACpC,UAAI,CAAC,MAAM,QAAQ,UAAU,KAAK,WAAW,WAAW,GAAG;AACzD,cAAM,IAAI,MAAM,kDAAkD;AAAA,MACpE;AACA,YAAM,OAAO,WAAW,MAAM,MAAM;AACpC,YAAM,KAAK,WAAW,MAAM,IAAI;AAChC,YAAM,OAAgC;AAAA,QACpC;AAAA,QACA,QAAQ,cAAc,MAAM,QAAQ;AAAA,MACtC;AAEA,UAAI,KAAK,KAAK,MAAM,MAAM;AACxB,aAAK,KAAK,IAAI;AAAA,MAChB,WAAW,QAAQ,IAAI;AACrB,aAAK,MAAM,IAAI;AACf,aAAK,IAAI,IAAI;AAAA,MACf,OAAO;AACL,aAAK,QAAQ,IAAI,WAAW,MAAM,QAAQ,KAAK;AAAA,MACjD;AACA,aAAO,OAAO,QAAQ,QAAQ,yBAAyB,EAAE,KAAK,CAAC;AAAA,IACjE;AAAA,EACF;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,oBAAoB;AAAA,QACnD,WAAW,EAAE,GAAG,KAAK,aAAa,yBAAyB;AAAA,QAC3D,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,uBAAuB;AAAA,MACvD;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,kBAAkB;AAAA,MACtC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,WAAW,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,eAAe;AAAA,MAC5C;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,kBAAkB,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,EAAE;AAAA,EAC3F;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,GAAG,KAAK,aAAa,6CAA6C;AAAA,QAC5E,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,uBAAuB;AAAA,MACvD;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,eAAe;AAAA,MACnC,OAAO;AAAA,QACL,QAAQ,WAAW,MAAM,QAAQ;AAAA,QACjC,MAAM,WAAW,MAAM,MAAM;AAAA,QAC7B,OAAO,WAAW,MAAM,OAAO;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,GAAG,KAAK,aAAa,YAAY;AAAA,QACvC,MAAM,EAAE,GAAG,KAAK,aAAa,4DAA4D;AAAA,MAC3F;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,QAAQ,eAAe,mBAAmB,cAAc,MAAM,IAAI,CAAC,CAAC,gBAAgB;AAAA,MACjG,MAAM,EAAE,MAAM,WAAW,MAAM,MAAM,EAAE;AAAA,IACzC,CAAC;AAAA,EACL;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,OAAO,WAAW,OAAO,QAAQ,OAAO,mBAAmB;AAAA,EAC7E;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,GAAG,IAAI;AAAA,QACf,OAAO,EAAE,GAAG,KAAK,aAAa,cAAc;AAAA,MAC9C;AAAA,MACA,sBAAsB;AAAA,IACxB;AAAA,IACA,cAAc;AAAA,IACd,SAAS,OAAO,MAAM,WACpB,OAAO,QAAQ,OAAO,gBAAgB;AAAA,MACpC,OAAO,EAAE,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,WAAW,MAAM,OAAO,EAAE;AAAA,IAC5E,CAAC;AAAA,EACL;AACF;AAEO,SAAS,SAAS,MAA0C;AACjE,SAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC1C;;;AFjmBA,IAAM,cAAc;AACpB,IAAM,iBAAiB;AAEvB,SAAS,oBAAoB,MAA8B;AACzD,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,aAAa,KAAK;AAAA,IAClB,aAAa,KAAK;AAAA,IAClB,aAAa,KAAK;AAAA,EACpB;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,aAAa,SAAS,eAAe;AAAA,IAC7C,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO,kBAAkB,wBAAwB,aAAa;AAAA,IAC5D,OAAO,MAAM,IAAI,mBAAmB;AAAA,EACtC,EAAE;AAEF,SAAO,kBAAkB,uBAAuB,OAAO,QAAQ;AAC7D,UAAM,OAAO,SAAS,IAAI,OAAO,IAAI;AACrC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,OAAO,IAAI,GAAG,CAAC;AAAA,MACtE;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAAQ,IAAI,OAAO,aAAa,CAAC,GAAG,MAAM;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,aAC3B,8BAA8B,IAAI,MAAM,MAAM,IAAI,OAAO;AAAA,EACvD,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,KAAK,UAAU,IAAI,MAAM,MAAM,CAAC,CAC5E,KACA,eAAe,QACb,IAAI,UACJ,OAAO,GAAG;AAChB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AAEpB,UAAQ,MAAM,sCAAsC,GAAG;AACvD,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ApiClient } from './api-client.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tool registry for the Visual Sentinel MCP server.
|
|
5
|
+
*
|
|
6
|
+
* Each tool wraps a single Visual Sentinel REST endpoint with a JSON Schema
|
|
7
|
+
* input and a structured handler. Public-tool handlers (DNS check, SSL check,
|
|
8
|
+
* speed test, website check, health) run without authentication; everything
|
|
9
|
+
* else requires `VS_API_KEY`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
interface ToolInput {
|
|
13
|
+
type: 'object';
|
|
14
|
+
properties: Record<string, unknown>;
|
|
15
|
+
required?: string[];
|
|
16
|
+
additionalProperties?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface ToolAnnotations {
|
|
19
|
+
title: string;
|
|
20
|
+
readOnlyHint: boolean;
|
|
21
|
+
destructiveHint: boolean;
|
|
22
|
+
idempotentHint: boolean;
|
|
23
|
+
openWorldHint: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface ToolDefinition {
|
|
26
|
+
name: string;
|
|
27
|
+
/** Human-readable title shown by MCP clients. */
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
annotations: ToolAnnotations;
|
|
31
|
+
inputSchema: ToolInput;
|
|
32
|
+
requiresAuth: boolean;
|
|
33
|
+
handler: (args: Record<string, unknown>, client: ApiClient) => Promise<unknown>;
|
|
34
|
+
}
|
|
35
|
+
declare const TOOLS: ToolDefinition[];
|
|
36
|
+
declare function findTool(name: string): ToolDefinition | undefined;
|
|
37
|
+
|
|
38
|
+
export { TOOLS, type ToolAnnotations, type ToolDefinition, findTool };
|