vigile_search
Search the Vigile registry for MCP servers and agent skills by keyword to evaluate safety and trust scores of third-party tools.
Instructions
Search the Vigile registry for MCP servers and agent skills by keyword. Returns matching entries with trust scores. Use this when you need to find servers by description or capability.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (e.g., 'filesystem', 'database', 'code execution') | |
| limit | No | Max results to return (default: 10, max: 50) |
Implementation Reference
- src/tools/search.ts:7-65 (handler)The main handler function `searchRegistry` that executes the vigile_search tool logic. It searches the Vigile registry for MCP servers and agent skills by keyword, making parallel API calls to both endpoints, then formats the results into a markdown table with trust scores and levels.
export async function searchRegistry( baseUrl: string, apiKey: string, query: string, limit?: number ): Promise<string> { const effectiveLimit = Math.min(limit || 10, 50); const qs = `q=${encodeURIComponent(query)}&limit=${effectiveLimit}`; // Search both servers and skills in parallel const [serverRes, skillRes] = await Promise.all([ fetchVigile(baseUrl, apiKey, `/api/v1/search/?${qs}`), fetchVigile(baseUrl, apiKey, `/api/v1/search/skills?${qs}`), ]); const servers = serverRes.ok && Array.isArray(serverRes.data) ? serverRes.data : []; const skills = skillRes.ok && Array.isArray(skillRes.data) ? skillRes.data : []; if (servers.length === 0 && skills.length === 0) { return [ `## Search: "${query}"`, "", "No results found in the Vigile registry.", "", "Try a different search term, or submit a server/skill for scanning at https://vigile.dev", ].join("\n"); } const lines = [`## Search: "${query}"`, ""]; // Server results if (servers.length > 0) { lines.push(`### MCP Servers (${servers.length} results)`, ""); lines.push("| Server | Score | Level | Source |"); lines.push("|--------|-------|-------|--------|"); for (const s of servers) { const emoji = trustLevelEmoji(s.trust_level); lines.push( `| [${s.name}](https://vigile.dev/server/${encodeURIComponent(s.name)}) | ${formatScore(s.trust_score)} | ${emoji} ${s.trust_level} | ${s.source} |` ); } } // Skill results if (skills.length > 0) { if (servers.length > 0) lines.push(""); lines.push(`### Agent Skills (${skills.length} results)`, ""); lines.push("| Skill | Score | Level | Platform |"); lines.push("|-------|-------|-------|----------|"); for (const s of skills) { const emoji = trustLevelEmoji(s.trust_level); lines.push( `| [${s.name}](https://vigile.dev/skill/${encodeURIComponent(s.name)}) | ${formatScore(s.trust_score)} | ${emoji} ${s.trust_level} | ${s.platform} |` ); } } return lines.join("\n"); } - src/index.ts:109-122 (registration)Registration of the vigile_search tool using `server.tool()`. Defines the tool name, description, and wires the handler to the `searchRegistry` function.
// ── Tool: vigile_search ── server.tool( "vigile_search", "Search the Vigile registry for MCP servers and agent skills by keyword. Returns matching entries with trust scores. Use this when you need to find servers by description or capability.", { query: z.string().min(1).max(200).describe("Search query (e.g., 'filesystem', 'database', 'code execution')"), limit: z.number().int().min(1).max(50).optional().describe("Max results to return (default: 10, max: 50)"), }, async ({ query, limit }) => { const result = await searchRegistry(API_BASE, API_KEY, query, limit); return { content: [{ type: "text" as const, text: result }] }; } ); - src/index.ts:114-117 (schema)Zod schema definition for vigile_search inputs: `query` (required string, 1-200 chars) and `limit` (optional integer, 1-50).
{ query: z.string().min(1).max(200).describe("Search query (e.g., 'filesystem', 'database', 'code execution')"), limit: z.number().int().min(1).max(50).optional().describe("Max results to return (default: 10, max: 50)"), }, - src/tools/api.ts:5-46 (helper)The `fetchVigile` helper function used by searchRegistry to make HTTP requests to the Vigile API. Handles authentication headers, error sanitization, and returns structured response data.
export async function fetchVigile( baseUrl: string, apiKey: string, path: string, options?: { method?: string; body?: string } ): Promise<{ ok: boolean; status: number; data: any }> { const headers: Record<string, string> = { "Content-Type": "application/json", "User-Agent": "vigile-mcp/0.1.7", }; if (apiKey) { headers["Authorization"] = `Bearer ${apiKey}`; } try { const res = await fetch(`${baseUrl}${path}`, { method: options?.method || "GET", headers, body: options?.body, }); const data = await res.json().catch(() => null); return { ok: res.ok, status: res.status, data }; } catch (error: any) { // Sanitize error message — don't leak internal details like // hostnames, ports, file paths, or stack traces const rawMsg = error?.message || "Unknown error"; const safeMsg = rawMsg.includes("ECONNREFUSED") || rawMsg.includes("ENOTFOUND") ? "API server unreachable" : rawMsg.includes("ETIMEDOUT") || rawMsg.includes("timeout") ? "Request timed out" : rawMsg.includes("ECONNRESET") ? "Connection reset" : "Connection failed"; return { ok: false, status: 0, data: { detail: safeMsg }, }; } } - src/tools/api.ts:48-65 (helper)Helper functions `trustLevelEmoji` and `formatScore` used by searchRegistry to format trust levels with emoji indicators and format numeric scores for display.
export function trustLevelEmoji(level: string): string { switch (level) { case "trusted": return "🟢"; case "caution": return "🟡"; case "risky": return "🟠"; case "dangerous": return "🔴"; default: return "⚪"; } } export function formatScore(score: number): string { return `${Math.round(score)}/100`; }