食谱管理MCP服务器

一个基于模型上下文协议(MCP)的服务器,用于持久化存储、检索和组织食谱文件,支持Markdown格式和YAML前端元数据。

  • by ecdeng
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 ecdeng/recipe-mcp-server

使用说明

个人配方管理器MCP服务器

一种模型上下文协议(MCP)服务器,允许ChatGPT持久存储、检索和组织配方文件。食谱存储为带有YAML frontmatter的Markdown文件,使其对人工智能友好且易于人类阅读。

特性

  • 永久存储:使用YAML frontmatter将食谱存储为Markdown文件
  • 三个核心工具:
    • save_recipe:使用元数据创建或更新食谱
    • read_recipe:检索配方内容
    • list_recipes:列出所有具有可选类别过滤的食谱
  • 安全:通过模糊UUID路径进行基于URL的身份验证
  • 部署:基于Docker的Render部署,具有持久磁盘存储

建筑

服务器使用:

  • 协议:HTTP上的模型上下文协议(MCP)+服务器发送事件(SSE)
  • 存储:包含YAML frontmatter的Markdown文件 /app/recipes
  • 认证:模糊安全-URL路径中嵌入UUID
  • 框架:支持SSE的FastAPI

项目结构

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

安装说明

地方发展

  1. 克隆存储库 (或导航到项目目录)

  2. 创建虚拟环境:

    python3 -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
  3. 安装依赖项:

    pip install -r requirements.txt
    
  4. 设置环境变量 (可选):

    export MCP_AUTH_UUID="your-uuid-here"  # Optional: set custom UUID
    export PORT=8000  # Optional: set custom port
    
  5. 运行服务器:

    python server.py
    

    服务器将于启动 http://localhost:8000

Docker本地测试

  1. 构建Docker镜像:

    docker build -t recipe-mcp-server .
    
  2. 运行容器:

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

    注意:对于本地测试,您可能需要挂载一个本地配方目录。

要渲染的部署

先决条件

  • 渲染帐户
  • GitHub存储库(可选,用于自动部署)

部署步骤

  1. 将代码推送到GitHub (如果使用GitHub集成)

  2. 在渲染时创建Web服务:

    • 转到渲染仪表板
    • 点击“新建+”→ “Web服务”
    • 连接您的GitHub存储库(或使用公共Git存储库)
  3. 配置服务:

    • 名字: recipe-mcp-server (或您喜欢的名字)
    • 运行时: Docker
    • 实例类型: Starter (或支持磁盘的任何层)
    • 生成命令:(留空,Docker处理此问题)
    • 启动命令:(留空,Dockerfile CMD处理此问题)
  4. 添加永久磁盘 (关键):

    • 在服务设置中,转到“磁盘”
    • 点击“添加磁盘”
    • 安装路径: /app/recipes
    • 尺寸: 1GB (根据需要进行调整)
    • 名字: recipe-storage
  5. 设置环境变量 (可选):

    • MCP_AUTH_UUID:身份验证路径的自定义UUID(如果未设置,将生成一个)
    • PORT:端口号(默认值:8000,Render会自动设置)
  6. 部署:

    • 点击“创建Web服务”
    • 等待部署完成
  7. 获取您的MCP端点URL:

    • 部署后,访问服务URL
    • 根端点(/)将显示MCP端点路径
    • 您的完整MCP URL将是: https://your-service.onrender.com/mcp-{uuid}/sse

连接到ChatGPT

  1. 获取您的MCP端点URL 从渲染服务(见上文)

  2. 打开ChatGPT开发者设置:

    • 转到ChatGPT设置
    • 导航到开发人员模式或MCP设置
    • 添加新的MCP服务器
  3. 配置MCP服务器:

    • 名字:配方管理器(或您的首选名称)
    • 统一资源定位符: https://your-service.onrender.com/mcp-{uuid}/sse
    • 类型:HTTP+SSE
  4. 保存并测试:

    • 服务器现在应该可以用于ChatGPT
    • 尝试让ChatGPT保存一个配方来测试连接

API 文档

工具: save_recipe

使用YAML frontmatter创建或更新配方文件。

端点: POST /mcp-{uuid}/sse/tools/save_recipe

请求体:

{
  "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
}

可选字段:

  • prep_time:准备时间(例如“15m”、“30分钟”)
  • cook_time:烹饪时间(例如“45米”、“1小时”)
  • servings:份数(整数)

响应:

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

工具: read_recipe

检索配方文件的完整内容(包括frontmatter)。

端点: POST /mcp-{uuid}/sse/tools/read_recipe

请求体:

{
  "filename": "spicy_tacos.md"
}

响应:

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

工具: list_recipes

列出所有配方文件,可选择按类别筛选。

端点: POST /mcp-{uuid}/sse/tools/list_recipes

请求体:

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

响应:

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

配方文件格式

食谱存储为带有YAML frontmatter的Markdown文件:

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

**Ingredients:**
- ...

**Instructions:**
1. ...

安全注意事项

基于URL的身份验证

服务器使用“模糊安全”-身份验证嵌入在URL路径本身中:

  • 生成(或通过以下方式设置)随机UUID MCP_AUTH_UUID 环境变量)
  • MCP端点仅在以下位置可访问 /mcp-{uuid}/sse
  • 如果有人不知道UUID,他们就无法访问服务器

重要:

  • 不要公开共享您的MCP URL
  • 如果URL被泄露,任何有URL的人都可以读/写你的食谱
  • 如果URL暴露,请考虑重新生成UUID

路径横向保护

服务器实现了严格的文件名验证:

  • 拒绝包含以下内容的文件名 ../ 或路径分隔符
  • 拒绝绝对路径
  • 只允许 .md 文件
  • 所有文件操作都限制为 /app/recipes

错误处理

  • 无效的文件名:返回400个带错误消息的错误请求
  • 缺少文件:返回404未找到
  • 正面无效:优雅地处理解析错误(如果需要,跳过列表中的文件)
  • 磁盘已满:返回500内部服务器错误

故障排除

服务器无法启动

  • 检查端口8000是否可用(或已设置 PORT 环境变量)
  • 验证是否安装了所有依赖项: pip install -r requirements.txt
  • 如果在Docker中运行,请检查Docker日志

食谱不持久

  • 在渲染时:验证持久磁盘是否已装载在 /app/recipes
  • 在Render仪表板中检查磁盘大小和使用情况
  • 验证磁盘是否正确连接到服务

MCP连接失败

  • 验证包含UUID路径的完整URL
  • 检查服务器是否正在运行且可访问
  • 测试根端点(/)获取正确的MCP路径
  • 检查渲染服务日志是否有错误

类别筛选不起作用

  • 验证配方是否具有有效的YAML frontmatter
  • 检查一下 category 字段设置在前台
  • 类别匹配不区分大小写

发展

在本地运行测试

测试服务器终结点:

# 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 '{}'

许可证

本项目按原样提供供个人使用。

支持

对于问题或疑问:

  1. 检查上面的故障排除部分
  2. 查看渲染服务日志
  3. 验证MCP端点URL是否正确