使用说明
Frappe的MCP服务器
安全的审计记录 模型上下文协议(MCP) Frappe的服务器。 此应用程序允许您以严格的粒度权限向MCP客户端(如AI代理)公开特定的DocType和操作,确保对Frappe数据的安全和受控访问。
特性
- 安全认证:专用
MCP User通过令牌或API密钥访问。 - 粒度允许表:明确允许特定的DocType和操作(创建、读取、更新、删除)。
- 现场水平控制:限制哪些字段可以读取或写入。
- 审计日志:每个请求都会记录延迟、状态和有效负载摘要。
- 严格验证:所有过滤器和输入都根据满列表进行验证。
安装
-
获取应用程序:
bench get-app https://github.com/mascor/frappe-mcp-server -
在您的网站上安装:
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。
- 首选 MCP文件类型允许列表.
- 为要公开的DocType创建新记录(例如。,
ToDo). - 检查要允许的操作(
Allow Read,Allow Create等等)。 - (可选)限制子表中的字段和筛选器,以实现更严格的安全性。
用法
服务器通过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服务器-测试报告
可用命令
| 命令 | 描述 | 参数 |
|---|---|---|
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
设置要求
-
安装MCP服务器应用程序 在您的Frappe网站上
bench get-app https://github.com/[repo]/frappe-mcp-server bench --site [your-site] install-app mcp_server -
创建API用户 (例如。,
mcp_user@example.com) -
生成API密钥 对于用户
- 转到用户→ API访问→ 生成密钥
-
分配适当的角色 API用户(例如系统管理员)
-
配置允许列表
- 转到“MCP文档类型允许列表”
- 添加要通过MCP公开的DocType
- 配置允许的操作(读取、创建、更新、删除、元)
-
配置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_keyapi_secretpasswordnew_passwordreset_password_key
即使用户DocType在Allowlist中,此服务器端筛选器也可以防止凭据泄漏。
3.输入消毒
- SQL注入保护:所有用户输入都通过Frappe的ORM参数化
- XSS保护:HTML内容被自动净化(例如。,
<script>→<script>) - 路径横向保护:DocType名称根据Allowlist进行验证
4.受保护的系统文档类型
默认情况下,以下敏感的DocType被阻止(不在Allowlist中):
DocType-系统架构Role-权限角色System Settings-全局配置Email Account-电子邮件凭据Error Log-系统错误(可能包含敏感数据)Scheduled Job Log-后台作业日志File-上传的文件MCP Doctype Allowlist-防止自我修改
安全最佳实践
用于生产部署
- 最小化允许列表:仅添加严格必要的DocType
- 限制操作:仅启用必需的操作(读取/创建/更新/删除)
- 使用字段限制:限制可以在筛选器中读取或使用的字段
- 单独的API用户:为MCP创建一个角色最少的专用用户
- 监控访问:定期查看API访问日志
- 旋转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 "<script>alert('XSS')</script>"
路径遍历
# 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 ║
╚══════════════════════════════════════════════════════════════╝