bbq_list_proteins
Discover available BBQ proteins with cooking information. Filter by category to find meats and their identifiers for use in BBQ recipes and temperature monitoring.
Instructions
List all supported protein types with their key cooking information.
Use this to discover available proteins and their identifiers for use with other tools.
Args:
category: Filter by category ('beef', 'pork', 'poultry', 'lamb', 'seafood', 'all')
response_format: 'markdown' or 'json'
Examples:
"What meats can you help me cook?" -> category='all'
"Show me beef options" -> category='beef'
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | Filter by protein category | all |
| response_format | No | Output format | markdown |
Implementation Reference
- src/index.ts:458-497 (handler)Executes the tool logic: filters PROTEIN_PROFILES by category, supports JSON or markdown output via formatProteinListMarkdownasync (params: ListProteinsInput) => { try { let proteins = Object.values(PROTEIN_PROFILES); if (params.category !== "all") { proteins = proteins.filter((p) => p.category === params.category); } if (params.response_format === "json") { const output = { category: params.category, count: proteins.length, proteins: proteins.map((p) => ({ type: p.type, displayName: p.displayName, category: p.category, usdaSafeTemp: p.usdaSafeTemp, recommendedMethods: p.recommendedMethods, hasStall: !!p.stallRange, donenessOptions: Object.keys(p.donenessTemps), })), }; return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }], structuredContent: output, }; } const markdown = formatProteinListMarkdown(proteins, params.category); return { content: [{ type: "text", text: markdown }], }; } catch (error) { const message = error instanceof Error ? error.message : "Unknown error occurred"; return { isError: true, content: [{ type: "text", text: `Error listing proteins: ${message}` }], }; }
- src/schemas/index.ts:143-153 (schema)Zod input schema defining category filter (enum) and response_formatexport const ListProteinsSchema = z .object({ category: z .enum(["beef", "pork", "poultry", "lamb", "seafood", "all"]) .default("all") .describe("Filter by protein category"), response_format: ResponseFormatSchema.describe("Output format"), }) .strict(); export type ListProteinsInput = z.infer<typeof ListProteinsSchema>;
- src/index.ts:435-499 (registration)Registers the bbq_list_proteins tool with MCP server, including title, description, schema, and annotationsserver.registerTool( "bbq_list_proteins", { title: "List Supported Proteins", description: `List all supported protein types with their key cooking information. Use this to discover available proteins and their identifiers for use with other tools. Args: - category: Filter by category ('beef', 'pork', 'poultry', 'lamb', 'seafood', 'all') - response_format: 'markdown' or 'json' Examples: - "What meats can you help me cook?" -> category='all' - "Show me beef options" -> category='beef'`, inputSchema: ListProteinsSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, }, async (params: ListProteinsInput) => { try { let proteins = Object.values(PROTEIN_PROFILES); if (params.category !== "all") { proteins = proteins.filter((p) => p.category === params.category); } if (params.response_format === "json") { const output = { category: params.category, count: proteins.length, proteins: proteins.map((p) => ({ type: p.type, displayName: p.displayName, category: p.category, usdaSafeTemp: p.usdaSafeTemp, recommendedMethods: p.recommendedMethods, hasStall: !!p.stallRange, donenessOptions: Object.keys(p.donenessTemps), })), }; return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }], structuredContent: output, }; } const markdown = formatProteinListMarkdown(proteins, params.category); return { content: [{ type: "text", text: markdown }], }; } catch (error) { const message = error instanceof Error ? error.message : "Unknown error occurred"; return { isError: true, content: [{ type: "text", text: `Error listing proteins: ${message}` }], }; } } );
- src/services/formatting.ts:141-179 (helper)Formats the filtered protein list into grouped markdown outputexport function formatProteinListMarkdown( proteins: ProteinProfile[], category?: string ): string { const categoryDisplay = category === "all" ? "All Proteins" : `${category?.charAt(0).toUpperCase()}${category?.slice(1)}`; let output = `## 🥩 ${categoryDisplay}\n\n`; // Group by category const grouped = proteins.reduce( (acc, protein) => { if (!acc[protein.category]) { acc[protein.category] = []; } acc[protein.category].push(protein); return acc; }, {} as Record<string, ProteinProfile[]> ); for (const [cat, prots] of Object.entries(grouped)) { output += `### ${cat.charAt(0).toUpperCase() + cat.slice(1)}\n\n`; for (const protein of prots) { const doneness = Object.keys(protein.donenessTemps)[0] as DonenessLevel; const temp = protein.donenessTemps[doneness]; output += `**${protein.displayName}** (\`${protein.type}\`)\n`; output += `- Target: ${temp}°F (${DONENESS_INFO[doneness]?.displayName || doneness})\n`; output += `- Methods: ${protein.recommendedMethods.map((m) => COOK_METHOD_INFO[m].displayName).join(", ")}\n`; if (protein.stallRange) { output += `- ⚠️ Stalls at ${protein.stallRange.start}-${protein.stallRange.end}°F\n`; } output += "\n"; } } return output; }
- src/constants.ts:23-23 (helper)Data source: PROTEIN_PROFILES object providing all supported proteins with cooking profiles, used by the handler to generate the listexport const PROTEIN_PROFILES: Record<ProteinType, ProteinProfile> = {