Reviewed-on: #14 Co-authored-by: Nicholas Ward <nicholaspward@outlook.com>
7.7 KiB
7.7 KiB
Formulation API & Model Context Protocol (MCP) Guide
Formulation exposes two programmatic interfaces for querying, scaling, costing, and manipulating culinary data:
- Model Context Protocol (MCP) Server: A standard stdio JSON-RPC server enabling AI assistants (Claude Desktop, Antigravity, Cursor, Gemini) to directly search, retrieve, cost, scale, and save recipes, ingredients, books, and inventory counts.
- REST Web API (
/api/v1/): HTTP JSON endpoints for external systems, webhooks, and programmatic integrations.
1. Model Context Protocol (MCP) Server
Starting the Server
npm run mcp
# or directly:
node scripts/mcp-server.mjs
Client Configuration Examples
Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json on Windows / ~/Library/Application Support/Claude/claude_desktop_config.json on macOS)
{
"mcpServers": {
"formulation": {
"command": "node",
"args": [
"C:\\Users\\nicholas\\Documents\\repos\\formulation\\scripts\\mcp-server.mjs"
]
}
}
}
Antigravity / Gemini (.gemini/config/mcp_config.json)
{
"mcpServers": {
"formulation": {
"command": "node",
"args": [
"scripts/mcp-server.mjs"
]
}
}
}
Cursor (.cursor/mcp.json)
{
"mcpServers": {
"formulation": {
"command": "node",
"args": ["scripts/mcp-server.mjs"]
}
}
}
MCP Tools Reference (15 Domain Tools)
| Tool | Parameters | Description |
|---|---|---|
search_recipes |
query?, category?, tag?, limit? |
Search recipes by keyword, category, or tag |
get_recipe |
id, scale_factor?, target_yield?, target_yield_unit? |
Retrieve full recipe formulation with optional scaling |
save_recipe |
id?, title, yield_quantity, yield_unit_id, components, steps, notes? |
Create or update a recipe formulation with validation |
delete_recipe |
id |
Safely archive a recipe from the active library |
calculate_recipe_cost |
recipe_id, currency? |
Compute itemized ingredient & sub-recipe cost breakdown |
calculate_recipe_nutrition |
recipe_id, serving_size_g? |
Compute nutrition facts panel (macros/micros) |
search_ingredients |
query?, category?, missing_cost?, limit? |
Search ingredients in the pantry catalog |
get_ingredient |
id |
Get ingredient detail with density, conversions, and prices |
save_ingredient |
id?, name, description?, categories?, tags?, aliases?, density? |
Create or update an ingredient with density & aliases |
delete_ingredient |
id |
Safely archive an ingredient (blocks if used in active recipes) |
convert_units |
ingredient_id?, quantity, from_unit, to_unit |
Convert culinary units safely using density data |
list_inventory_counts |
status? ('all' | 'open' | 'completed') |
List inventory counting sessions |
get_inventory_count |
id |
Get full count sheet with locations, items, unit costs, and valuations |
list_recipe_books |
(none) | List recipe books (collections) with recipe counts |
get_recipe_book |
id |
Get recipe book details with ordered included recipes |
save_recipe_book |
id?, name, description?, recipe_ids? |
Create or update a recipe book / collection |
export_database_backup |
(none) | Export complete JSON backup of all 25 SQLite tables |
get_database_stats |
(none) | Get table entity counts across the database |
2. REST Web API Specification (/api/v1/)
All REST endpoints return standard JSON envelopes:
- Success:
{ "success": true, "data": ... } - Error:
{ "success": false, "error": "Description" }
Recipes
List Recipes
GET /api/v1/recipes?q=biscotti&limit=10
Get Recipe Details & Dynamic Scaling
GET /api/v1/recipes/chocolate_biscotti?scale=2
Calculate Scaled Quantities
POST /api/v1/recipes/chocolate_biscotti/scale
Content-Type: application/json
{
"target_yield": 100,
"target_yield_unit": "each"
}
Itemized Cost Rollup
GET /api/v1/recipes/chocolate_biscotti/cost?currency=USD
Nutrition Facts Rollup
GET /api/v1/recipes/chocolate_biscotti/nutrition
Create Recipe
POST /api/v1/recipes
Content-Type: application/json
{
"title": "Vanilla Glaze",
"yield_quantity": 250,
"yield_unit_id": "gram",
"yield_servings": 10,
"categories": ["sauce"],
"components": [
{
"name": "Main",
"items": [
{ "ingredient_id": "confectioners_sugar", "quantity": 200, "unit_id": "gram" },
{ "ingredient_id": "milk", "quantity": 45, "unit_id": "gram" },
{ "ingredient_id": "vanilla_extract", "quantity": 5, "unit_id": "gram" }
]
}
],
"steps": [
{ "instruction": "In a medium bowl, whisk confectioners sugar, milk, and vanilla extract until smooth." }
]
}
Update Recipe
PUT /api/v1/recipes/vanilla_glaze
Archive Recipe
DELETE /api/v1/recipes/vanilla_glaze
Ingredients
List Ingredients
GET /api/v1/ingredients?q=sugar&limit=10
Get Ingredient Details
GET /api/v1/ingredients/sugar
Create Ingredient
POST /api/v1/ingredients
Content-Type: application/json
{
"name": "Matcha Powder",
"description": "Ceremonial Japanese green tea powder",
"categories": ["tea", "flavoring"],
"tags": ["japanese", "beverage"],
"aliases": [{ "name": "Matcha" }],
"density": {
"mass_quantity": 60,
"mass_unit_id": "gram",
"volume_quantity": 0.25,
"volume_unit_id": "cup_us"
}
}
Update Ingredient
PUT /api/v1/ingredients/matcha_powder
Archive Ingredient
DELETE /api/v1/ingredients/matcha_powder
(Fails safely with HTTP 409 Conflict if ingredient is referenced by active recipes.)
Recipe Books / Collections
List Recipe Books
GET /api/v1/collections
Get Recipe Book
GET /api/v1/collections/baking_essentials
Create Recipe Book
POST /api/v1/collections
Content-Type: application/json
{
"name": "Holiday Pastries",
"description": "Seasonal baked goods collection",
"recipe_ids": ["chocolate_biscotti", "cinnamon_sugar"]
}
Update Recipe Book
PUT /api/v1/collections/holiday_pastries
Archive Recipe Book
DELETE /api/v1/collections/holiday_pastries
Inventory Counts
List Counting Sessions
GET /api/v1/inventory/counts?status=all
Start New Count Session
POST /api/v1/inventory/counts
Content-Type: application/json
{
"title": "August End-of-Month Count",
"counted_at": "2026-08-31T18:00:00Z",
"notes": "Full kitchen and pantry audit",
"prepopulate": true
}
Get Count Sheet & Extended Valuation
GET /api/v1/inventory/counts/count_2026_08_week3
Save Count Items & Update Status
PUT /api/v1/inventory/counts/count_2026_08_week3
Content-Type: application/json
{
"status": "completed",
"items": [
{ "ingredient_id": "flour_all_purpose", "location_id": "loc_dry_storage", "quantity": 15000, "unit_id": "gram" },
{ "ingredient_id": "sugar", "location_id": "loc_dry_storage", "quantity": 25, "unit_id": "pound" }
]
}
Unit Conversions
POST /api/v1/convert
Content-Type: application/json
{
"ingredient_id": "salt",
"quantity": 2,
"from_unit": "tbsp",
"to_unit": "gram"
}
{
"success": true,
"data": {
"from": { "quantity": 2, "unit_id": "tbsp" },
"to": { "quantity": 36.52, "unit_id": "gram" },
"ingredient_id": "salt",
"method": "ingredient_measure_conversion"
}
}
Database Backups
GET /api/app/backup/export
POST /api/app/backup/validate
POST /api/app/backup/import?mode=replace|merge