LeoWalker's picture
feat(auth): add FastAPI token proxy for MCP HTTP, dual-server mode in main.py; add tests; docs and env example
aee78d5

FoodWise MCP Server

Overview

The FoodWise MCP (Model Context Protocol) server provides AI agents with comprehensive inventory management capabilities. It exposes food inventory data and operations through a standardized protocol that enables intelligent assistance with meal planning, expiration management, and kitchen organization.

Architecture

The MCP server is built using FastMCP and organized into three focused modules:

src/foodwise/mcp_server/
β”œβ”€β”€ main.py                # Entry point & primitive registration  
β”œβ”€β”€ fastmcp_tools.py       # πŸ”§ CRUD operations (12 tools)
β”œβ”€β”€ fastmcp_resources.py   # πŸ“‚ Live data sources (4 resources)
β”œβ”€β”€ fastmcp_prompts.py     # πŸ“ Workflow templates (5 prompts)
└── README.md              # This documentation

Design Principles

  • Separation of Concerns: Each module handles one type of MCP primitive
  • Live Data: Resources always fetch fresh data from Notion (no caching)
  • Defensive Programming: Graceful handling of missing/invalid Notion data
  • Type Safety: Full type annotations for better maintainability

MCP Primitives

πŸ”§ Tools (Actions)

Defined in fastmcp_tools.py

Inventory Tools (5):

Tool Purpose Key Parameters
get_inventory Retrieve inventory items with filtering filter_type, category, storage_type, expiring_days
add_inventory_item Add new food items name, category, storage_type, quantity, unit + optional fields
search_inventory_items Find items by name/category search_term, search_type
update_inventory_item Modify existing items page_id, updated_data
remove_inventory_item Archive items page_id

Shopping Tools (7):

Tool Purpose Key Parameters
get_shopping_list Retrieve shopping items with filtering store, priority, status
add_shopping_item Add new shopping items item_name, quantity, unit, store, priority + optional fields
update_shopping_item Modify shopping items page_id + update fields
remove_shopping_item Archive shopping items page_id
create_shopping_from_recipe Generate shopping list from recipe recipe_ingredients, servings, preferred_store
optimize_shopping_by_store Organize shopping by store Returns store-grouped lists with tips
move_purchased_to_inventory Move purchased items to inventory purchased_item_ids

πŸ“‚ Resources (Live Data)

Defined in fastmcp_resources.py

Inventory Resources (2):

Resource URI Purpose Data Provided
inventory://items Complete inventory state All items with metadata
inventory://expiring-items Expiration alerts Items expiring in next 7 days (urgent/moderate/upcoming)

Shopping Resources (2):

Resource URI Purpose Data Provided
shopping://list Current shopping list All shopping items organized by status
shopping://by-store Shopping organized by store Items grouped by preferred store with totals

πŸ“ Prompts (Workflow Templates)

Defined in fastmcp_prompts.py

Prompt Purpose Key Features
add_item_helper Guide item entry Required/optional fields, validation, organization tips
meal_planning_assistant Plan meals using available inventory Prioritize expiring items, provide recipes, shopping lists
expiration_manager Handle items expiring soon Safety assessment, usage strategies, preservation methods
shopping_list_optimizer Create smart shopping lists Avoid duplicates, consider storage capacity
smart_shopping_assistant General shopping guidance Budget management, store optimization, duplicate prevention

Integration

Claude Desktop Configuration

Local MCP Server

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "foodwise": {
      "command": "uv",
      "args": ["run", "python", "-m", "foodwise.mcp_server"],
      "cwd": "/path/to/FoodWise",
      "env": {
        "MCP_LOG_LEVEL": "INFO"
      }
    }
  }
}

For development with debug logging:

{
  "mcpServers": {
    "foodwise-dev": {
      "command": "uv", 
      "args": ["run", "fastmcp", "dev", "src/foodwise/mcp_server/main.py"],
      "cwd": "/path/to/FoodWise",
      "env": {
        "MCP_LOG_LEVEL": "DEBUG"
      }
    }
  }
}

Remote MCP Server βœ… NEW!

For remote access without local setup:

{
  "mcpServers": {
    "foodwise-remote": {
      "command": "npx",
      "args": ["supergateway", "--streamableHttp", "https://leowalker-foodwise-remote-mcp.hf.space/mcp/"]
    }
  }
}

Remote MCP Server with Token (Recommended)

Enable a lightweight token gate compatible with Desktop + supergateway.

{
  "mcpServers": {
    "foodwise-remote": {
      "command": "npx",
      "args": [
        "supergateway",
        "--streamableHttp",
        "https://<your-space>.hf.space/mcp/?key=$MCP_AUTH_TOKEN"
      ]
    }
  }
}

Notes:

  • Prefer the Authorization: Bearer header in general; ?key= is provided for bridge compatibility.
  • When MCP_AUTH_TOKEN is set, main.py runs MCP upstream on 127.0.0.1:7870 and the proxy on public PORT (7860).
  • Health check (no auth): GET /health β†’ { "status": "ok" }.

🌐 Remote Deployment: The MCP server is deployed on HuggingFace Spaces using Docker with:

  • FastMCP HTTP transport
  • Python 3.12 + uv package management
  • Automatic OAuth-free access for MCP clients
  • Environment secrets managed in HuggingFace Space settings

Requirements for Remote Access:

  • npx installed (comes with Node.js)
  • supergateway package (automatically installed via npx)
  • Internet connection

Usage Examples

Get expiring items:

Use the inventory://expiring-items resource to see what needs attention

Plan meals:

Use the meal_planning_assistant prompt with current inventory data

Add new item:

Use add_inventory_item tool with: milk, Dairy, Refrigerator, 1, gallon

Data Backend

The MCP server connects to a Notion database that stores all inventory data. The FoodWiseNotionClient handles:

  • βœ… CRUD operations on inventory items
  • βœ… Filtering and search functionality
  • βœ… Expiration date calculations
  • βœ… Defensive handling of flexible Notion schema

Database Schema

Key Notion properties:

  • Name (title): Item identifier
  • Category (select): Food category (Dairy, Raw Meat, etc.)
  • Storage Type (select): Pantry/Refrigerator/Freezer
  • Quantity (number): Amount available
  • Unit (text): Measurement unit
  • Best By Date (date): Expiration date
  • Location/Shelf (text): Specific storage location
  • Tags (multi-select): Organization labels

Error Handling

The server implements comprehensive error handling:

  • Notion API errors: Graceful degradation with error messages
  • Missing data: Defensive programming with sensible defaults
  • Type mismatches: Safe conversion with fallbacks
  • Network issues: Timeout handling and retry logic

Development

Running the Server

# Basic usage (stdio transport)
uv run python -m foodwise.mcp_server

# With debug logging
MCP_LOG_LEVEL=DEBUG uv run python -m foodwise.mcp_server

# Using FastMCP CLI with HTTP transport
uv run fastmcp run src/foodwise/mcp_server/main.py --transport http --port 8080

# Custom server name
MCP_SERVER_NAME="MyFoodWise" uv run python -m foodwise.mcp_server

Remote Deployment (HTTP Mode)

For HuggingFace Spaces or similar cloud deployment:

# Using the main.py entry point (for Docker/cloud deployment)
uv run python main.py

# With custom environment
HOST=0.0.0.0 PORT=7860 ENVIRONMENT=production uv run python main.py

# Local HTTP testing (before deployment)
HOST=127.0.0.1 PORT=7860 uv run python main.py

Remote Server Features:

  • HTTP transport for web accessibility
  • Environment-based configuration
  • Docker containerization ready
  • OAuth-free MCP client access

Testing Integration

# Test with manual MCP client
uv run python scripts/manual_test.py

# Test with FastMCP dev server (includes MCP Inspector)
uv run fastmcp dev src/foodwise/mcp_server/main.py

Remote Server Testing

# Test remote MCP server with MCP Inspector
npx @modelcontextprotocol/inspector "https://leowalker-foodwise-remote-mcp.hf.space/mcp/"

# Test supergateway bridge locally
npx supergateway --streamableHttp "https://leowalker-foodwise-remote-mcp.hf.space/mcp/" --logLevel debug

# Verify remote server health
curl -I "https://leowalker-foodwise-remote-mcp.hf.space/mcp/"

Remote Testing Notes:

  • MCP Inspector provides interactive testing interface
  • supergateway bridges HTTP MCP to stdio for Claude Desktop
  • Remote server responds on /mcp/ endpoint with Streamable-HTTP protocol

Adding New Primitives

  1. Tools: Add to fastmcp_tools.py and register in register_inventory_tools()
  2. Resources: Add to fastmcp_resources.py and register in register_resources()
  3. Prompts: Add template constant and function to fastmcp_prompts.py

Configuration

The server follows FastMCP best practices for minimal configuration:

  • Environment Variables:
    • MCP_SERVER_NAME - Override server name (default: "FoodWise")
    • MCP_LOG_LEVEL - Set logging level (DEBUG, INFO, WARNING, ERROR)
  • CLI Arguments: Use fastmcp run with transport and port options
  • Zero Config: Works out of the box with sensible defaults

Future Enhancements

  • External recipe API integration
  • Configurable meal suggestion algorithms
  • Batch operations for bulk inventory updates
  • Advanced filtering and sorting options
  • Integration with grocery delivery APIs
  • Nutritional information tracking

For more information about the broader FoodWise project, see the main README.md.