Files
formulation/docs/api-and-mcp-guide.md
T
nicholasandnicholas 2a1e16ed30
Build & Deploy Formulation / Build & Push Image (push) Failing after 15s
Build & Deploy Formulation / deploy (push) Skipped
add core features (#14)
Reviewed-on: #14
Co-authored-by: Nicholas Ward <nicholaspward@outlook.com>
2026-08-18 18:22:34 -05:00

7.7 KiB

Formulation API & Model Context Protocol (MCP) Guide

Formulation exposes two programmatic interfaces for querying, scaling, costing, and manipulating culinary data:

  1. 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.
  2. 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