We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mdlopresti/mealie-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Shopping List Resources for Mealie MCP Server
Provides shopping list information as MCP resources.
"""
from typing import Optional
# Handle imports for both module and script execution
try:
from ..client import MealieClient, MealieAPIError
except ImportError:
# Running as a script, use absolute imports
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from client import MealieClient, MealieAPIError
def get_shopping_lists() -> str:
"""
Get all shopping lists from Mealie.
URI: shopping://lists
Returns:
Formatted shopping lists with items, counts, and status
"""
try:
client = MealieClient()
# Get all shopping lists
response = client.get("/api/households/shopping/lists")
client.close()
# Format output
output = ["# Shopping Lists", ""]
# Handle paginated response
shopping_lists = []
if response:
if isinstance(response, dict) and "items" in response:
shopping_lists = response["items"]
elif isinstance(response, list):
shopping_lists = response
else:
shopping_lists = [response]
if not shopping_lists:
output.append("*No shopping lists found*")
return "\n".join(output)
output.append(f"**Total Lists**: {len(shopping_lists)}")
output.append("")
# Display each list
for shopping_list in shopping_lists:
list_name = shopping_list.get("name", "Unnamed List")
list_id = shopping_list.get("id", "")
output.append(f"## {list_name}")
output.append("")
# Metadata
created_at = shopping_list.get("createdAt", "")
updated_at = shopping_list.get("updateAt", "")
if created_at:
output.append(f"- **Created**: {created_at}")
if updated_at:
output.append(f"- **Last Updated**: {updated_at}")
# Get items
items = shopping_list.get("listItems", [])
if items:
output.append(f"- **Total Items**: {len(items)}")
# Count checked vs unchecked
checked_count = sum(1 for item in items if item.get("checked", False))
unchecked_count = len(items) - checked_count
output.append(f"- **Completed**: {checked_count}/{len(items)}")
output.append("")
# Display unchecked items first
if unchecked_count > 0:
output.append("### To Buy")
output.append("")
for item in items:
if not item.get("checked", False):
display = item.get("display", "")
quantity = item.get("quantity", "")
unit = item.get("unit")
food = item.get("food")
note = item.get("note", "")
# Build item text
item_text = ""
if display:
# Use display if available
item_text = display
else:
# Build from components
parts = []
if quantity:
parts.append(str(quantity))
if unit and isinstance(unit, dict):
parts.append(unit.get("name", ""))
elif unit:
parts.append(str(unit))
if food and isinstance(food, dict):
parts.append(food.get("name", ""))
elif food:
parts.append(str(food))
item_text = " ".join(parts) if parts else "Unknown item"
output.append(f"- [ ] {item_text}")
if note:
output.append(f" - *{note}*")
output.append("")
# Display checked items
if checked_count > 0:
output.append("### Already Purchased")
output.append("")
for item in items:
if item.get("checked", False):
display = item.get("display", "")
quantity = item.get("quantity", "")
unit = item.get("unit")
food = item.get("food")
note = item.get("note", "")
# Build item text
item_text = ""
if display:
item_text = display
else:
parts = []
if quantity:
parts.append(str(quantity))
if unit and isinstance(unit, dict):
parts.append(unit.get("name", ""))
elif unit:
parts.append(str(unit))
if food and isinstance(food, dict):
parts.append(food.get("name", ""))
elif food:
parts.append(str(food))
item_text = " ".join(parts) if parts else "Unknown item"
output.append(f"- [x] {item_text}")
if note:
output.append(f" - *{note}*")
output.append("")
else:
output.append("- **Total Items**: 0")
output.append("")
output.append("*No items in this list*")
output.append("")
return "\n".join(output)
except MealieAPIError as e:
return f"Error fetching shopping lists: {e}"
except Exception as e:
return f"Unexpected error: {e}"
def get_shopping_list_detail(list_id: str) -> str:
"""
Get detailed information about a specific shopping list.
URI: shopping://{list_id}
Args:
list_id: Shopping list ID
Returns:
Formatted shopping list with all items and details
"""
try:
client = MealieClient()
shopping_list = client.get(f"/api/households/shopping/lists/{list_id}")
client.close()
if not shopping_list:
return f"Shopping list '{list_id}' not found"
# Format output
output = []
# Header
list_name = shopping_list.get("name", "Unnamed List")
output.append(f"# {list_name}")
output.append("")
# Metadata
created_at = shopping_list.get("createdAt", "")
updated_at = shopping_list.get("updateAt", "")
if created_at:
output.append(f"**Created**: {created_at}")
if updated_at:
output.append(f"**Last Updated**: {updated_at}")
output.append("")
# Get items
items = shopping_list.get("listItems", [])
if items:
# Count checked vs unchecked
checked_count = sum(1 for item in items if item.get("checked", False))
unchecked_count = len(items) - checked_count
output.append(f"**Progress**: {checked_count}/{len(items)} items completed")
output.append("")
# Display unchecked items first
if unchecked_count > 0:
output.append("## To Buy")
output.append("")
for item in items:
if not item.get("checked", False):
display = item.get("display", "")
quantity = item.get("quantity", "")
unit = item.get("unit")
food = item.get("food")
note = item.get("note", "")
# Build item text
item_text = ""
if display:
item_text = display
else:
parts = []
if quantity:
parts.append(str(quantity))
if unit and isinstance(unit, dict):
parts.append(unit.get("name", ""))
elif unit:
parts.append(str(unit))
if food and isinstance(food, dict):
parts.append(food.get("name", ""))
elif food:
parts.append(str(food))
item_text = " ".join(parts) if parts else "Unknown item"
output.append(f"- [ ] {item_text}")
if note:
output.append(f" - *{note}*")
output.append("")
# Display checked items
if checked_count > 0:
output.append("## Already Purchased")
output.append("")
for item in items:
if item.get("checked", False):
display = item.get("display", "")
quantity = item.get("quantity", "")
unit = item.get("unit")
food = item.get("food")
note = item.get("note", "")
# Build item text
item_text = ""
if display:
item_text = display
else:
parts = []
if quantity:
parts.append(str(quantity))
if unit and isinstance(unit, dict):
parts.append(unit.get("name", ""))
elif unit:
parts.append(str(unit))
if food and isinstance(food, dict):
parts.append(food.get("name", ""))
elif food:
parts.append(str(food))
item_text = " ".join(parts) if parts else "Unknown item"
output.append(f"- [x] {item_text}")
if note:
output.append(f" - *{note}*")
output.append("")
else:
output.append("*No items in this list*")
output.append("")
return "\n".join(output)
except MealieAPIError as e:
return f"Error fetching shopping list '{list_id}': {e}"
except Exception as e:
return f"Unexpected error: {e}"
if __name__ == "__main__":
"""Test shopping list resources."""
import sys
from pathlib import Path
# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
from dotenv import load_dotenv
from client import MealieClient
load_dotenv()
print("Testing Shopping List Resources")
print("=" * 70)
print()
# Test 1: Get all shopping lists
print("TEST 1: Get All Shopping Lists")
print("-" * 70)
result = get_shopping_lists()
print(result)
print()
print()
# Test 2: Get shopping list detail (if any lists exist)
print("TEST 2: Get Shopping List Detail")
print("-" * 70)
client = MealieClient()
try:
response = client.get("/api/households/shopping/lists")
# Handle paginated response
shopping_lists = []
if response:
if isinstance(response, dict) and "items" in response:
shopping_lists = response["items"]
elif isinstance(response, list):
shopping_lists = response
else:
shopping_lists = [response]
if shopping_lists and len(shopping_lists) > 0:
test_list_id = shopping_lists[0].get("id", "")
if test_list_id:
print(f"Testing with list ID: {test_list_id}")
print()
result = get_shopping_list_detail(test_list_id)
print(result)
else:
print("No shopping lists found to test with")
else:
print("No shopping lists found to test with")
except Exception as e:
print(f"Error: {e}")
finally:
client.close()