Skip to content

ecdeng/recipe-mcp-server

Repository files navigation

Personal Recipe Manager MCP Server

A Model Context Protocol (MCP) server that allows ChatGPT to persistently store, retrieve, and organize recipe files. Recipes are stored as Markdown files with YAML frontmatter, making them both AI-friendly and human-readable.

Features

  • Persistent Storage: Recipes stored as Markdown files with YAML frontmatter
  • Three Core Tools:
    • save_recipe: Create or update recipes with metadata
    • read_recipe: Retrieve recipe content
    • list_recipes: List all recipes with optional category filtering
  • Security: URL-based authentication via obscure UUID path
  • Deployment: Docker-based deployment on Render with persistent disk storage

Architecture

The server uses:

  • Protocol: Model Context Protocol (MCP) over HTTP + Server-Sent Events (SSE)
  • Storage: Markdown files with YAML frontmatter in /app/recipes
  • Authentication: Security by obscurity - UUID embedded in URL path
  • Framework: FastAPI with SSE support

Project Structure

recipe-mcp-server/
├── server.py              # Main MCP server implementation
├── Dockerfile             # Docker configuration
├── requirements.txt       # Python dependencies
├── .dockerignore          # Docker ignore patterns
├── .gitignore            # Git ignore patterns
├── README.md             # This file
└── recipes/              # Local testing directory (not in Docker)
    └── .gitkeep

Setup Instructions

Local Development

  1. Clone the repository (or navigate to the project directory)

  2. Create a virtual environment:

    python3 -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
  3. Install dependencies:

    pip install -r requirements.txt
  4. Set environment variables (optional):

    export MCP_AUTH_UUID="your-uuid-here"  # Optional: set custom UUID
    export PORT=8000  # Optional: set custom port
  5. Run the server:

    python server.py

    The server will start on http://localhost:8000

Docker Local Testing

  1. Build the Docker image:

    docker build -t recipe-mcp-server .
  2. Run the container:

    docker run -p 8000:8000 -v $(pwd)/recipes:/app/recipes recipe-mcp-server

    Note: For local testing, you may want to mount a local recipes directory.

Deployment to Render

Prerequisites

  • Render account
  • GitHub repository (optional, for automatic deployments)

Deployment Steps

  1. Push code to GitHub (if using GitHub integration)

  2. Create a Web Service on Render:

    • Go to Render Dashboard
    • Click "New +" → "Web Service"
    • Connect your GitHub repository (or use public Git repository)
  3. Configure the service:

    • Name: recipe-mcp-server (or your preferred name)
    • Runtime: Docker
    • Instance Type: Starter (or any tier that supports Disks)
    • Build Command: (leave empty, Docker handles this)
    • Start Command: (leave empty, Dockerfile CMD handles this)
  4. Add Persistent Disk (CRITICAL):

    • In the service settings, go to "Disks"
    • Click "Add Disk"
    • Mount Path: /app/recipes
    • Size: 1GB (adjust as needed)
    • Name: recipe-storage
  5. Set Environment Variables (optional):

    • MCP_AUTH_UUID: Custom UUID for authentication path (if not set, one will be generated)
    • PORT: Port number (default: 8000, Render sets this automatically)
  6. Deploy:

    • Click "Create Web Service"
    • Wait for deployment to complete
  7. Get your MCP endpoint URL:

    • After deployment, visit the service URL
    • The root endpoint (/) will show the MCP endpoint path
    • Your full MCP URL will be: https://your-service.onrender.com/mcp-{uuid}/sse

Connecting to ChatGPT

  1. Get your MCP endpoint URL from the Render service (see above)

  2. Open ChatGPT Developer Settings:

    • Go to ChatGPT settings
    • Navigate to Developer Mode or MCP settings
    • Add a new MCP server
  3. Configure the MCP server:

    • Name: Recipe Manager (or your preferred name)
    • URL: https://your-service.onrender.com/mcp-{uuid}/sse
    • Type: HTTP + SSE
  4. Save and test:

    • The server should now be available to ChatGPT
    • Try asking ChatGPT to save a recipe to test the connection

API Documentation

Tool: save_recipe

Creates or updates a recipe file with YAML frontmatter.

Endpoint: POST /mcp-{uuid}/sse/tools/save_recipe

Request Body:

{
  "filename": "spicy_tacos.md",
  "content": "# Spicy Tacos\n\n**Ingredients:**\n- ...",
  "category": "Dinner",
  "tags": ["mexican", "spicy", "easy"],
  "prep_time": "15m",
  "cook_time": "20m",
  "servings": 4
}

Optional Fields:

  • prep_time: Preparation time (e.g., "15m", "30 minutes")
  • cook_time: Cooking time (e.g., "45m", "1 hour")
  • servings: Number of servings (integer)

Response:

{
  "success": true,
  "message": "Recipe 'spicy_tacos.md' saved successfully",
  "filename": "spicy_tacos.md"
}

Tool: read_recipe

Retrieves the full content of a recipe file (including frontmatter).

Endpoint: POST /mcp-{uuid}/sse/tools/read_recipe

Request Body:

{
  "filename": "spicy_tacos.md"
}

Response:

{
  "success": true,
  "filename": "spicy_tacos.md",
  "content": "---\ncategory: Dinner\ntags: [mexican, spicy, easy]\n---\n# Spicy Tacos\n\n..."
}

Tool: list_recipes

Lists all recipe files, optionally filtered by category.

Endpoint: POST /mcp-{uuid}/sse/tools/list_recipes

Request Body:

{
  "category": "Dinner"  // Optional
}

Response:

{
  "success": true,
  "recipes": ["spicy_tacos.md", "lasagna.md"],
  "count": 2
}

Recipe File Format

Recipes are stored as Markdown files with YAML frontmatter:

---
category: "Dinner"
tags: ["italian", "pasta", "comfort-food"]
prep_time: "30m"
---
# Classic Lasagna

**Ingredients:**
- ...

**Instructions:**
1. ...

Security Considerations

URL-Based Authentication

The server uses "security by obscurity" - the authentication is embedded in the URL path itself:

  • A random UUID is generated (or set via MCP_AUTH_UUID environment variable)
  • The MCP endpoint is only accessible at /mcp-{uuid}/sse
  • If someone doesn't know the UUID, they cannot access the server

Important:

  • Do not share your MCP URL publicly
  • If the URL is compromised, anyone with the URL can read/write your recipes
  • Consider regenerating the UUID if the URL is exposed

Path Traversal Protection

The server implements strict filename validation:

  • Rejects filenames containing ../ or path separators
  • Rejects absolute paths
  • Only allows .md files
  • All file operations are constrained to /app/recipes

Error Handling

  • Invalid filenames: Returns 400 Bad Request with error message
  • Missing files: Returns 404 Not Found
  • Invalid frontmatter: Gracefully handles parsing errors (skips file in list if needed)
  • Disk full: Returns 500 Internal Server Error

Troubleshooting

Server won't start

  • Check that port 8000 is available (or set PORT environment variable)
  • Verify all dependencies are installed: pip install -r requirements.txt
  • Check Docker logs if running in Docker

Recipes not persisting

  • On Render: Verify the persistent disk is mounted at /app/recipes
  • Check disk size and usage in Render dashboard
  • Verify the disk is properly attached to the service

MCP connection fails

  • Verify the full URL including the UUID path
  • Check that the server is running and accessible
  • Test the root endpoint (/) to get the correct MCP path
  • Check Render service logs for errors

Category filtering not working

  • Verify recipes have valid YAML frontmatter
  • Check that the category field is set in the frontmatter
  • Category matching is case-insensitive

Development

Running Tests Locally

Test the server endpoints:

# Start the server
python server.py

# In another terminal, test save_recipe
curl -X POST http://localhost:8000/mcp-{uuid}/sse/tools/save_recipe \
  -H "Content-Type: application/json" \
  -d '{"filename": "test.md", "content": "# Test Recipe", "category": "Test"}'

# Test read_recipe
curl -X POST http://localhost:8000/mcp-{uuid}/sse/tools/read_recipe \
  -H "Content-Type: application/json" \
  -d '{"filename": "test.md"}'

# Test list_recipes
curl -X POST http://localhost:8000/mcp-{uuid}/sse/tools/list_recipes \
  -H "Content-Type: application/json" \
  -d '{}'

License

This project is provided as-is for personal use.

Support

For issues or questions:

  1. Check the troubleshooting section above
  2. Review Render service logs
  3. Verify the MCP endpoint URL is correct

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors