Frappe MCP服务器

一个安全的、具有审计日志功能的模型上下文协议(MCP)服务器,用于Frappe,通过严格的权限控制实现对Frappe数据的安全访问。

  • by mascor
  • Python
  • 本地部署
  • 4 星标
  • 更新于
在 GitHub 查看 mascor/frappe-mcp-server

使用说明

Frappe的MCP服务器

安全的审计记录 模型上下文协议(MCP) Frappe的服务器。 此应用程序允许您以严格的粒度权限向MCP客户端(如AI代理)公开特定的DocType和操作,确保对Frappe数据的安全和受控访问。

特性

  • 安全认证:专用 MCP User 通过令牌或API密钥访问。
  • 粒度允许表:明确允许特定的DocType和操作(创建、读取、更新、删除)。
  • 现场水平控制:限制哪些字段可以读取或写入。
  • 审计日志:每个请求都会记录延迟、状态和有效负载摘要。
  • 严格验证:所有过滤器和输入都根据满列表进行验证。

安装

  1. 获取应用程序:

    bench get-app https://github.com/mascor/frappe-mcp-server
    
  2. 在您的网站上安装:

    bench --site <your-site> install-app mcp_server
    

配置

1.设置MCP用户和设置

您可以使用附带的安装脚本,使用默认用户和令牌快速配置服务器:

bench --site <your-site> execute mcp_server.setup.setup_mcp

这将:

  • 创建用户 mcp@example.com (如果不存在)。
  • 生成安全 X-MCP-Token 并将其保存在 MCP服务器设置.
  • 启用MCP服务器。

或者,转到 MCP服务器设置 在桌面上手动配置。

2.配置允许列表

默认情况下, 不允许访问。您必须明确允许DocTypes。

  1. 首选 MCP文件类型允许列表.
  2. 为要公开的DocType创建新记录(例如。, ToDo).
  3. 检查要允许的操作(Allow Read, Allow Create等等)。
  4. (可选)限制子表中的字段和筛选器,以实现更严格的安全性。

用法

服务器通过API公开标准MCP工具。

认证

服务器支持 API密钥 身份验证(建议用于MCP客户端)。

包括 Authorization 所有请求中的标头。

工具

mcp_ping

健康检查和版本信息。

curl -X POST https://<yoursite>/api/method/mcp_server.api.ping \
     -H "Authorization: token <api_key>:<api_secret>"

search_docs

使用筛选器搜索文档。

{
    "doctype": "ToDo",
    "filters": {"status": "Open"}
}

create_doc

创建新文档。

{
    "doctype": "ToDo",
    "data": {
        "description": "New Task from MCP"
    }
}

update_doc

更新现有文档。

{
    "doctype": "ToDo",
    "name": "TODO-0001",
    "data": {
        "status": "Closed"
    }
}

审计日志

检查 MCP审核日志 在Desk中查看所有请求的历史记录,包括成功/失败状态、延迟和差异。

许可证

麻省理工学院

快速连接:MCP客户端

要从AI客户端(如Claude Desktop或Cursor)连接到此服务器,请使用官方Python客户端:

frappe mcp客户端

按照客户端存储库中的安装和设置说明开始。

Frappe MCP服务器-测试报告

可用命令

命令 描述 参数
ping 检查服务器连接 无
search_docs 搜索文档 doctype (必填), filters (可选), fields (可选)
get_doc 获取特定文档 doctype (必填), name (必填)
create_doc 创建新文档 doctype (必填), data (必填)
update_doc 更新现有文档 doctype (必填), name (必填), data (必填)
get_meta 获取DocType元数据 doctype (必填)
delete_doc 删除文档 doctype (必填), name (必填)

测试结果总结

A节:标准DocType操作

测试 DocType 操作 状态
A1 注释 create_doc ✅ 通行证
A2 注释 get_doc ✅ 通行证
A3 备注 更新.doc ✅ 通行证
A4 备注 搜索文档 ✅ 通行证
A5 注释 删除_doc ✅ 通行证
A6 事件 create_doc ✅ 通行证
A7 事件 获取信息 ✅ 通行证
A8 事件 delete_doc ✅ 通行证

B部分:过滤器和字段

测试 描述 状态
B1 带过滤器的search_docs ✅ 通行证
B2 带字段的search_docs ✅ 通行证
B3 带过滤器+字段的search_docs ✅ 通行证

C节:边缘情况/错误处理

测试 描述 预期 状态
C1 get_doc不存在文档 404找不到 ✅ 通行证
C2 create_doc缺少必填字段 417预期失败 ✅ 通行证
C3 update_doc不存在文档 404找不到 ✅ 通行证
C4 delete_doc不存在文档 404找不到 ✅ 通行证
C5 get_meta不存在DocType 403禁止 ✅ 通行证

D节:权限

测试 描述 状态
D1 在允许的DocType(用户)上搜索_docs ✅ 通行证
D2 获取不允许的DocType(角色)上的数据 ✅ 通行证(403)

🎉 最终结果:18/18测试通过


测试示例

1.ping

检查服务器连接状态。

答复:

{
  "status": "ok",
  "site": "your-site.example.com",
  "user": "mcp_user@example.com"
}

2.获取数据

获取DocType的结构。

请求:

doctype: "ToDo"

答复:

{
  "doctype": "ToDo",
  "fields": [
    {
      "fieldname": "status",
      "label": "Status",
      "fieldtype": "Select",
      "options": "Open\\nClosed\\nCancelled",
      "reqd": 0,
      "default": "Open"
    },
    {
      "fieldname": "priority",
      "label": "Priority",
      "fieldtype": "Select",
      "options": "High\\nMedium\\nLow",
      "reqd": 0,
      "default": "Medium"
    },
    {
      "fieldname": "date",
      "label": "Due Date",
      "fieldtype": "Date",
      "reqd": 0,
      "default": "Today"
    },
    {
      "fieldname": "description",
      "label": "Description",
      "fieldtype": "Text Editor",
      "reqd": 1
    }
  ],
  "issingle": 0,
  "istable": 0
}

3.create_doc

创建新文档。

请求:

doctype: "ToDo"
data: {
  "status": "Open",
  "priority": "High",
  "description": "Test task created via MCP"
}

答复:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:41.295624",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0,
  "status": "Open",
  "priority": "High",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "doctype": "ToDo"
}

4.search_docs

使用可选筛选器和字段搜索文档。

请求(基本):

doctype: "ToDo"

答复:

[
  {"name": "todo001"},
  {"name": "todo002"},
  {"name": "todo003"}
]

请求(带筛选器和字段):

doctype: "ToDo"
filters: {"status": "Open"}
fields: ["name", "status", "priority", "description"]

答复:

[
  {
    "name": "todo001",
    "status": "Open",
    "priority": "Medium",
    "description": "Test task 1"
  },
  {
    "name": "todo002",
    "status": "Open",
    "priority": "High",
    "description": "Test task 2"
  }
]

5.get_doc

按名称获取特定文档。

请求:

doctype: "ToDo"
name: "abc123xyz"

答复:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "status": "Open",
  "priority": "High",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:41.295624",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0
}

6.update_doc

更新现有文档。

请求:

doctype: "ToDo"
name: "abc123xyz"
data: {
  "status": "Closed",
  "priority": "Low"
}

答复:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:59.096886",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0,
  "status": "Closed",
  "priority": "Low",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "doctype": "ToDo"
}

7.delete_doc

删除文档。

请求:

doctype: "ToDo"
name: "abc123xyz"

答复:

{
  "status": "deleted",
  "name": "abc123xyz"
}

错误响应(找不到文档):

HTTP 404 Not Found

设置要求

  1. 安装MCP服务器应用程序 在您的Frappe网站上

    bench get-app https://github.com/[repo]/frappe-mcp-server
    bench --site [your-site] install-app mcp_server
    
  2. 创建API用户 (例如。, mcp_user@example.com)

  3. 生成API密钥 对于用户

    • 转到用户→ API访问→ 生成密钥
  4. 分配适当的角色 API用户(例如系统管理员)

  5. 配置允许列表

    • 转到“MCP文档类型允许列表”
    • 添加要通过MCP公开的DocType
    • 配置允许的操作(读取、创建、更新、删除、元)
  6. 配置MCP客户端 使用API证书


允许列表配置

MCP服务器使用Allowlist来控制哪些DocType是可访问的。对于每种DocType,您可以配置:

选项 描述
允许读取(获取、搜索) 许可证 get_doc 和 search_docs
允许创建 许可证 create_doc
允许更新 许可证 update_doc
允许删除 许可证 delete_doc
允许元(架构) 许可证 get_meta
最大页面长度 限制结果 search_docs (0=默认值)
允许的字段(读取) 限制返回哪些字段(空=全部)
允许的筛选器 限制哪些字段可以在筛选器中使用(空=全部)

错误代码

HTTP代码 含义 常见原因
200 成功 操作已完成
403 Forbidden DocType不在Allowlist中或不允许操作
404 未找到 文档或DocType不存在
417 预期失败 验证错误(例如,缺少必填字段)
500 内部服务器错误 服务器端错误(检查日志)

故障排除

问题 原因 解决方案
403 Forbidden 缺少权限 将角色分配给API用户或添加 @frappe.whitelist() 装饰师
403 Forbidden 在所有调用中 缺少Allowlist条目 将DocType添加到MCP DocType Allowlist
403 Forbidden 关于特定操作 操作未启用 在Allowlist中启用该操作
403 Forbidden 带筛选器 不允许使用筛选器字段 将字段添加到允许的筛选器中或为所有字段留空
404 Not Found 文档不存在 验证文档名称
417 Expectation Failed 找不到模块 安装/重新安装MCP服务器应用程序
417 Expectation Failed 验证错误 检查DocType中的必填字段
500 Internal Server Error 代码错误 运行 bench --site [site] logs

安全说明

  • 只有明确添加到Allowlist中的DocTypes才可访问
  • 必须明确启用每个操作(读取、创建、更新、删除、元)
  • 所有操作都需要API身份验证
  • 考虑在生产环境中限制敏感的DocType(用户、角色等)

安全审计报告

概述

Frappe MCP服务器经过了全面的安全测试,以确保其安全用于生产。所有15项安全测试均已成功通过。


安全测试结果

身份验证和授权

测试 描述 结果
S1 敏感字段(密码、api_key、api_secret)不可访问 ✅ 通行证
S2 系统文档类型(DocType)被阻止 ✅ 通行证
S3 角色文档类型被阻止 ✅ 通行证
S4 系统设置被阻止 ✅ 通行证
S5 电子邮件帐户(凭据)被阻止 ✅ 通行证
S6 允许列表自我修改被阻止 ✅ 通行证

注入攻击

测试 描述 结果
S7 过滤器中的SQL注入 ✅ 通行证
S8 文档名称中的SQL注入 ✅ 通行证
S12 文档内容中的XSS ✅ PASS(消毒)
S14 路径穿越攻击 ✅ 通行证

数据保护

测试 描述 结果
S9 错误日志访问被阻止 ✅ 通行证
S10 计划作业日志访问被阻止 ✅ 通行证
S11 文件DocType访问被阻止 ✅ 通行证
S13 从用户自动筛选敏感字段 ✅ 通行证
S15 阻止特权升级 ✅ 通行证

安全功能

1.基于允许列表的访问控制

只有DocTypes明确添加到 MCP文件类型允许列表 可通过API访问。每个DocType都可以配置细粒度权限:

  • 允许读取(获取、搜索)
  • 允许创建
  • 允许更新
  • 允许删除
  • 允许元(架构)

2.自动灵敏场滤波

以下字段为 自动删除 从所有API响应中,无论用户权限或Allowlist配置如何:

  • api_key
  • api_secret
  • password
  • new_password
  • reset_password_key

即使用户DocType在Allowlist中,此服务器端筛选器也可以防止凭据泄漏。

3.输入消毒

  • SQL注入保护:所有用户输入都通过Frappe的ORM参数化
  • XSS保护:HTML内容被自动净化(例如。, <script> → &lt;script&gt;)
  • 路径横向保护:DocType名称根据Allowlist进行验证

4.受保护的系统文档类型

默认情况下,以下敏感的DocType被阻止(不在Allowlist中):

  • DocType -系统架构
  • Role -权限角色
  • System Settings -全局配置
  • Email Account -电子邮件凭据
  • Error Log -系统错误(可能包含敏感数据)
  • Scheduled Job Log -后台作业日志
  • File -上传的文件
  • MCP Doctype Allowlist -防止自我修改

安全最佳实践

用于生产部署

  1. 最小化允许列表:仅添加严格必要的DocType
  2. 限制操作:仅启用必需的操作(读取/创建/更新/删除)
  3. 使用字段限制:限制可以在筛选器中读取或使用的字段
  4. 单独的API用户:为MCP创建一个角色最少的专用用户
  5. 监控访问:定期查看API访问日志
  6. 旋转API键:定期重新生成API凭据

允许列表配置示例

DocType: Customer
├── Allow Read: ✅
├── Allow Create: ❌
├── Allow Update: ❌
├── Allow Delete: ❌
├── Allow Meta: ✅
├── Allowed Fields: ["name", "customer_name", "email"]
└── Allowed Filters: ["name", "customer_name"]

此配置允许对具有受限字段的客户记录进行只读访问。


经过测试的攻击向量

SQL注入

# Attempted attack
search_docs(doctype="ToDo", filters={"status": "Open'; DROP TABLE tabToDo; --"})

# Result: Query safely parameterized, no data loss

XSS(跨站脚本)

# Attempted attack
create_doc(doctype="ToDo", data={"description": "<script>alert('XSS')</script>"})

# Result: Content sanitized to "&lt;script&gt;alert('XSS')&lt;/script&gt;"

路径遍历

# Attempted attack
get_doc(doctype="../../../etc/passwd", name="root")

# Result: 403 Forbidden (DocType not in Allowlist)

权限提升

# Attempted attack
update_doc(doctype="User", name="attacker@example.com", data={"user_type": "Administrator"})

# Result: 403 Forbidden (Update not allowed on User DocType)

合规摘要

类别 状态
身份验证 ✅ 需要API密钥/机密
授权 ✅ 基于允许列表的访问控制
数据保护 ✅ 敏感字段自动过滤
输入验证 ✅ SQL/XSS/路径遍历保护
审计跟踪 ✅ 标准压裂测井

最终结果

╔══════════════════════════════════════════════════════════════╗
║                    SECURITY AUDIT PASSED                     ║
║                                                              ║
║                    15/15 Tests Successful                    ║
║                                                              ║
║          ✅ Ready for Production Deployment                  ║
╚══════════════════════════════════════════════════════════════╝