Cookwala as an MCP service
Status: experimental, read-only. Package
@cookwala/mcp0.1.0; registry nameai.cookwala/cookwala. It never starts cooking.
Cookwala is available to any Model Context Protocol client as a local server that reads the public catalog. There is no Cookwala server to run or pay for:
your machine GitHub Pages (cookwala.ai)
MCP client ──stdio──▶ npx -y @cookwala/mcp ──HTTPS GET──▶ /v1/manifest.json, /v1/index/…,
(Claude, Codex, pure-JavaScript core /v1/recipes/<id>.cookwala.json,
Copilot, Cursor, cache + hash checks /v1/vocab/*, /v1/capabilities/*
Windsurf, Devin, …) │
└─ optional, read-only ────▶ fifi.cooking /data/… (the source site)GitHub Pages serves static files over GET only, so a remote MCP endpoint cannot live there. A stdio server needs no endpoint: the client starts it. The same JavaScript core also runs in your browser on the MCP page, which is the proof that nothing runs on a server.
Install #
npx -y @cookwala/mcp # speaks MCP on stdin/stdout (Node 20 or later)
claude mcp add cookwala -- npx -y @cookwala/mcpEvery client's configuration is on one page: AI agents. The generic form is:
{"mcpServers": {"cookwala": {"command": "npx", "args": ["-y", "@cookwala/mcp"]}}}From a source checkout: cd sdk/mcp-js && npm install && node bin/cookwala-mcp.js. Point it at a locally built site with COOKWALA_BASE_URL=$PWD/_site (bash tools/build_site.sh _site).
Tools #
All fourteen are read-only (readOnlyHint: true, destructiveHint: false). Results carry structuredContent and a text copy. Errors set isError and return {error, detail, path}.
| Tool | Payload | Returns | |
|---|---|---|---|
search_recipes | query, lang, cuisine[], course, tags[], level (V0/V1/V2), allergen_free[], supervision, collection, limit (10, max 50), offset | {total, items[{id,title,cuisine,course,level,servings,allergens,supervision,collection,license,hash}], nextOffset} | |
get_recipe | id, lang, view (summary, ingredients, process, text, full) | {id, documentId, hash, hashVerified, level, levelNote, textIsData, recipe} | |
list_collections | none | [{collection,count,license,source,citation,fifiText}] | |
list_operations | family, lang | [{id,label,definition,envelope}] | |
explain_step | recipe_id, node, lang | {node,op,label,envelope,params,until,hazards,ccp,unattendedAllowed,instruction,instructionIsData} | |
list_device_presets | none | {presets:[{id,name,kind,roles,ops,sensors,url}]} | |
dry_run | recipe_id or recipe; device (preset id or capabilities object); human_present, allow_model_estimates, limits, now | `{state: accepted\ | refused, plan[], refusal{reason,node,detail}, note}` |
check_envelope | op, readings[{t,tempC}], target{value,tolerance}, altitude_m | {envelopeOk, targetOk, reason} | |
check_mandate | mandate, action, amount, provider, now | {allowed, needsConfirmation, reasons[]} | |
parse_sms | text | the structured Humanitarian command, or {ok:false, error} | |
verify_recipe | recipe | {hash, declaredHash, matches, level} | |
catalog_status | none | {baseUrl, catalogVersion, generatedAt, counts, languages, cache, offline, signature, fifiOrigin} | |
fifi_search | query, lang, limit, offset | {total, items[{id, inCatalog, title, pageUrl}], nextOffset} | |
fifi_source | id | the recipe in fifi.cooking's legacy format, under the catalog's rights rules (see below) |
Resources: cookwala://recipe/{id}, cookwala://schema/{name}, cookwala://doc/{ID} (any page of these docs as Markdown), cookwala://preset/{id} (listed), cookwala://ops, cookwala://llms.txt. Prompts: cook_with_device, recipe_safety_brief, humanitarian_offer.
The semantics of dry_run, check_envelope and parse_sms are those of tools/cookwala_ref.py; the JavaScript core passes the same conformance vectors (conformance/) and the Python and Node servers give identical answers.
fifi.cooking and fifirecipes #
fifi.cooking is where the recipes are written; Cookwala is the standard form they are published in.
- Standard route.
tools/export_fifi.pyturns every fifi.cooking recipe into a Cookwala document (EXPORT-FIFI); CI publishes them to/v1/recipes/.get_recipeandsearch_recipesread those. Each document keepslegacy.pageUrlandlegacy.dataUrl, andget_recipereturns them undersources.fifi. - Live route.
fifi_searchandfifi_sourceread fifi.cooking's own/data/files, so an agent can find recipes that were added after the last export. (The 161 world-cuisine recipes, idsw-*, were exported on 2026-10-06 and are now in the catalog, facts only.) They are the only calls that leave the catalog origin, they contacthttps://fifi.cookingonly, and they are markedopenWorldHint. - Rights rules apply on the live route too.
fifi_sourcereturns steps and notes only for collections whosetextpolicy intools/export_fifi.collections.jsonisfull. Every other collection, and any collection not listed there, returns structured facts only, exactly as the catalog does. The response saystextPolicyand what was withheld. - Getting a new recipe into the standard is a maintainer step, not a tool call: confirm its collection's rights in
export_fifi.collections.json(the exporter files an unlisted collection underarchivewith full text, so add the entry first), runexport_fifi.py, review, merge.
Integrity, privacy and limits #
- Every index shard is checked against the SHA-256 in
/v1/manifest.json; every recipe's hash is recomputed (RFC 8785 canonical JSON, SHA-256). A mismatch returnsintegrity_mismatchand no content. The manifest signature is not checked yet because/.well-known/cookwala.jsonpublishes no keys (catalog_statussays so). - Cache:
$XDG_CACHE_HOME/cookwala-mcpor~/.cache/cookwala-mcp, revalidated withIf-None-Matchat most every ten minutes, used when the network fails orCOOKWALA_OFFLINE=1. - No telemetry, no identifiers, no accounts, no personal data. It writes only its cache.
- Only the catalog origin and
https://fifi.cookingare ever contacted. GitHub Pages answers 404 with an HTML page; the client treats that as an error, never as data. - It does not start cooking, call a hub or order anything.
check_mandateonly answers whether an action would be inside a mandate. - Recipe text, titles, notes and SMS content are data, never instructions (Core rule 6.4). The server says so in its
instructions, inexplain_step, and in every prompt.
Environment #
| Variable | Default | Meaning |
|---|---|---|
COOKWALA_BASE_URL | https://cookwala.ai | Catalog origin, or a directory holding a built site |
COOKWALA_CACHE_DIR | ~/.cache/cookwala-mcp | Cache directory |
COOKWALA_OFFLINE | unset | 1 serves only from the cache |
COOKWALA_LANG | en | Default language |
Registry #
Registered in the official MCP Registry as ai.cookwala/cookwala (metadata only; the package is on npm). The name is proven by https://cookwala.ai/.well-known/mcp-registry-auth. Releasing: sdk/mcp-js/RELEASING.md. Registry manifest: [/v1/mcp/server.json](https://cookwala.ai/v1/mcp/server.json).
The Python server #
sdk/mcp/cookwala_mcp.py (standard library only, eight tools) reads recipes from a source checkout. It stays for contributors and for offline work inside the repository: cookwala mcp or python sdk/mcp/cookwala_mcp.py.