Pepesto Parse (recipe → structured ingredients)
pepesto_parseParse a recipe from a URL, free-form text, or image into structured ingredients, nutrition, and instructions for building a shopping cart.
Instructions
Parse a recipe from a URL, free-form text, or image into a structured object: title, ingredients, nutrition, instructions, and a KgToken you can pass to pepesto_products to build a real cart. Once the response is returned, show recipe title, image if available (json property image_url, don't search for external images, skip rendering the Pepesto image if the image has webp extesion), ingredients, steps, nutrition summary, allergens clearly marked, and portions/servings if available. Don't show kg_token, but mark and save it for the next steps (e.g., /products call).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| recipe_url | No | Publicly crawlable recipe URL. | |
| recipe_text | No | Free-form recipe text. | |
| recipe_image | No | Base64-encoded recipe image. | |
| locale | No | BCP 47 locale, e.g. 'en-GB', 'de-CH'. | |
| generate_image | No | Whether to generate a shareable image of the recipe. |
Implementation Reference
- src/tools/parse.ts:6-45 (registration)Registers the 'pepesto_parse' tool with the MCP server, including its name, description, and input schema.
export function registerParseTool(server: McpServer, client: PepestoClient): void { server.registerTool( "pepesto_parse", { title: "Pepesto Parse (recipe → structured ingredients)", description: "Parse a recipe from a URL, free-form text, or image into a structured object: title, " + "ingredients, nutrition, instructions, and a KgToken you can pass to pepesto_products to " + "build a real cart. Once the response is returned, show recipe title, " + "image if available (json property `image_url`, don't search for external images, " + "skip rendering the Pepesto image if the image has webp extesion), " + "ingredients, steps, nutrition summary, allergens clearly marked, and portions/servings if available. " + "Don't show kg_token, but mark and save it for the next steps (e.g., /products call).", inputSchema: { recipe_url: z .string() .url() .optional() .describe("Publicly crawlable recipe URL."), recipe_text: z .string() .optional() .describe("Free-form recipe text."), recipe_image: z .string() .optional() .describe("Base64-encoded recipe image."), locale: z .string() .optional() .describe("BCP 47 locale, e.g. 'en-GB', 'de-CH'."), generate_image: z .boolean() .optional() .describe("Whether to generate a shareable image of the recipe."), }, }, async (args) => runTool(() => client.post("/parse", args)), ); } - src/tools/parse.ts:19-41 (schema)Input schema for pepesto_parse: accepts optional recipe_url (URL), recipe_text (free text), recipe_image (base64), locale (BCP 47), and generate_image (boolean).
inputSchema: { recipe_url: z .string() .url() .optional() .describe("Publicly crawlable recipe URL."), recipe_text: z .string() .optional() .describe("Free-form recipe text."), recipe_image: z .string() .optional() .describe("Base64-encoded recipe image."), locale: z .string() .optional() .describe("BCP 47 locale, e.g. 'en-GB', 'de-CH'."), generate_image: z .boolean() .optional() .describe("Whether to generate a shareable image of the recipe."), }, - src/tools/parse.ts:43-44 (handler)Handler that POSTs the validated arguments to the /parse endpoint via the PepestoClient.
async (args) => runTool(() => client.post("/parse", args)), ); - src/tools/_runner.ts:9-27 (helper)Helper utility that wraps tool execution, serializing success results as JSON and catching errors (including PepestoApiError) into error responses.
export async function runTool(fn: () => Promise<unknown>): Promise<ToolResult> { try { const result = await fn(); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } catch (err) { const msg = err instanceof PepestoApiError ? err.message : err instanceof Error ? `Error: ${err.message}` : `Error: ${String(err)}`; return { content: [{ type: "text", text: msg }], isError: true, }; } } - src/client.ts:33-68 (helper)PepestoClient.post() performs the actual HTTP POST to the Pepesto API, used by the tool handler to call /parse.
async post<T = unknown>(endpoint: string, body: unknown): Promise<T> { if (!this.apiKey) { throw new Error( "PEPESTO_API_KEY is not set. See the README (\"Getting an API key\") for how to " + "obtain one.", ); } const path = endpoint.startsWith("/") ? endpoint : `/${endpoint}`; const url = `${this.baseUrl}${path}`; const headers: Record<string, string> = { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${this.apiKey}`, }; const res = await this.fetchImpl(url, { method: "POST", headers, body: JSON.stringify(body ?? {}), }); const text = await res.text(); if (!res.ok) { throw new PepestoApiError(res.status, path, text); } if (!text) { return {} as T; } try { return JSON.parse(text) as T; } catch { return text as unknown as T; } } }