get_server_detail
Obtain the full record for a specific MCP server, including summary, install snippet, use cases, FAQ, and selection guidance, from the mcpcatalogs.com directory.
Instructions
Get the full record for a single MCP server: summary, install snippet, use cases, FAQ, 'when to choose / when NOT', and links.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Server slug, normally "{author}-{repo}". Example: "modelcontextprotocol-server-postgres". You can find slugs via search_mcp_servers or list_top first. |
Implementation Reference
- src/tools.ts:133-213 (handler)Main handler function for get_server_detail. Queries the database by slug, validates active status, and builds a detailed markdown response including summary, categories, when-to-choose, when-NOT-to-choose, alternatives, overview, use cases, installation, FAQ, and links.
export async function handleDetail(args: { slug: string }) { const { data, error } = await db() .from("mcp_servers") .select(SERVER_COLS) .eq("slug", args.slug) .maybeSingle(); if (error) return asMarkdownText(`Lookup error: ${error.message}`); if (!data) return asMarkdownText(`No server with slug "${args.slug}".\n\nTry searching: \`search_mcp_servers\``); const s = data as ServerRow; if (s.status !== "active") { return asMarkdownText( `Server "${args.slug}" exists but is not active (status: ${s.status}). It's excluded from the public directory.`, ); } const summary = pick(s.ai_summary) ?? s.description ?? "(no summary)"; const longDesc = pick(s.ai_long_desc); const useCases = pick(s.ai_use_cases) as string[] | null; const installMd = pick(s.ai_install_md); const faq = s.ai_faq?.en ?? s.ai_faq?.zh ?? null; const whenChoose = pick(s.ai_when_to_choose); const whenNotChoose = pick(s.ai_when_not_to_choose); const parts: string[] = []; parts.push(`# ${s.name}${s.is_official ? " (official)" : ""}`); parts.push( `by **${s.author}** · ★${s.stars.toLocaleString()}` + (s.smithery_uses_30d != null ? ` · ${s.smithery_uses_30d.toLocaleString()} uses/30d` : "") + (s.ai_quality_score != null ? ` · composite ${s.ai_quality_score}/100` : "") + (s.last_commit_at ? ` · last commit ${s.last_commit_at.slice(0, 10)}` : ""), ); parts.push(""); parts.push(summary); if (s.ai_categories && s.ai_categories.length > 0) { parts.push(""); parts.push(`**Categories:** ${s.ai_categories.join(", ")}`); } if (whenChoose) { parts.push(""); parts.push(`## When to choose this\n${whenChoose}`); } if (whenNotChoose) { parts.push(""); parts.push(`## When NOT to choose this\n${whenNotChoose}`); } if (s.ai_alternatives && s.ai_alternatives.length > 0) { parts.push(""); parts.push(`**Comparable tools:** ${s.ai_alternatives.join(", ")}`); } if (longDesc) { parts.push(""); parts.push(`## Overview\n${longDesc}`); } if (useCases && useCases.length > 0) { parts.push(""); parts.push(`## Use cases\n${useCases.map((u) => `- ${u}`).join("\n")}`); } if (installMd) { parts.push(""); parts.push(`## Installation\n${installMd}`); } if (faq && faq.length > 0) { parts.push(""); parts.push("## FAQ"); for (const item of faq) { parts.push(`**${item.q}**\n${item.a}\n`); } } parts.push(""); parts.push("---"); parts.push(`Detail page: ${detailUrl(s.slug)}`); if (s.repo_url) parts.push(`GitHub: ${s.repo_url}`); parts.push(`Last refreshed: ${s.updated_at.slice(0, 10)}`); return asMarkdownText(parts.join("\n")); } - src/tools.ts:124-131 (schema)Zod schema for the get_server_detail tool input. Defines the 'slug' parameter as a non-empty string with documentation on format and how to find slugs.
export const detailSchema = { slug: z .string() .min(1) .describe( 'Server slug, normally "{author}-{repo}". Example: "modelcontextprotocol-server-postgres". You can find slugs via search_mcp_servers or list_top first.', ), }; - src/index.ts:39-44 (registration)Registration of the get_server_detail tool with the MCP server, linking the name, description, schema, and handler together.
server.tool( "get_server_detail", "Get the full record for a single MCP server: summary, install snippet, use cases, FAQ, 'when to choose / when NOT', and links.", detailSchema, async (args) => handleDetail(args), ); - src/tools.ts:48-52 (helper)Helper function asMarkdownText which wraps text into the MCP content block format used by the handler's return value.
function asMarkdownText(text: string) { // MCP content block. We never use isError=true for "not found" because // callers should treat that as a valid result, not a tool failure. return { content: [{ type: "text" as const, text }] }; } - src/tools.ts:18-22 (helper)Helper function 'pick' used to extract the English (or fallback Chinese) value from bilingual JSONB fields, used extensively in the handler.
function pick<T>(obj: { en?: T; zh?: T } | null | undefined): T | null { // English is canonical for the MCP server output — LLMs work in English by // default and zh fallback would force code-switching mid-citation. return obj?.en ?? obj?.zh ?? null; }