BFF Save Feature
Backend Function (BFF) save feature is an optional switch that allows AI to create and modify Backend Function scripts through MCP tools.
This feature is disabled by default and must be explicitly enabled in MCP configuration. Once enabled, AI can automatically save BFF scripts to the platform, use with caution.
Why Need a Separate Switch?
Backend Function is server-side code with certain sensitivity and risks:
- ✅ Efficiency: AI can directly create and modify BFF scripts without manual copy-paste
- ⚠️ Potential Risk: Incorrect BFF scripts may affect production environment
- ⚠️ Permission Control: Not all team members should have BFF modification permissions
- ⚠️ Audit Requirement: Need to track who (including AI) modified BFF scripts
Therefore, we designed the BFF save feature as an optional switch, allowing teams to decide whether to enable it based on actual situations.
How to Enable
Method 1: npx Startup (Recommended)
Add --enable-bff-save parameter in MCP configuration:
Claude Desktop / Claude Code Configuration Example:
{
"mcpServers": {
"lovrabet-dataset": {
"command": "npx",
"args": [
"-y",
"@lovrabet/dataset-mcp-server",
"--enable-bff-save"
],
"env": {
"LOVRABET_APP_CODE": "your-app-code"
}
}
}
}
Cursor / Windsurf Configuration Example:
{
"mcpServers": {
"lovrabet-dataset": {
"command": "npx",
"args": [
"-y",
"@lovrabet/dataset-mcp-server",
"--enable-bff-save"
],
"env": {
"LOVRABET_APP_CODE": "your-app-code"
}
}
}
}
Method 2: Global Installation Startup
If you have globally installed @lovrabet/dataset-mcp-server:
{
"mcpServers": {
"lovrabet-dataset": {
"command": "lovrabet-dataset-mcp",
"args": ["--enable-bff-save"],
"env": {
"LOVRABET_APP_CODE": "your-app-code"
}
}
}
}
Method 3: Start from Source
{
"mcpServers": {
"lovrabet-dataset": {
"command": "node",
"args": [
"/path/to/lovrabet-dataset-mcp/dist/index.js",
"--enable-bff-save"
],
"env": {
"LOVRABET_APP_CODE": "your-app-code"
}
}
}
}
Deprecated Parameter
⚠️ --dangerously-bff-save (Deprecated)
The old parameter --dangerously-bff-save is deprecated, functionality is identical to --enable-bff-save.
If your configuration uses the old parameter, recommend migrating:
// ❌ Old parameter (deprecated)
"args": ["--dangerously-bff-save"]
// ✅ New parameter (recommended)
"args": ["--enable-bff-save"]
Tools Available After Enabling
After enabling --enable-bff-save, MCP will provide the following 3 additional tools:
1. list_bff_scripts - List All Backend Functions
Get all BFF scripts under the application (only ENDPOINT type).
Parameters:
{
appCode?: string; // Application code (optional, use environment variable)
cookie?: string; // Authentication cookie (optional, use stored after login)
}
Return Example:
[
{
"id": 123,
"name": "getUserInfo",
"description": "Get user detailed information",
"scriptType": "ENDPOINT",
"createTime": "2026-03-20 10:30:00",
"updateTime": "2026-03-26 14:20:00",
"createUser": "user@example.com"
}
]
Use Cases:
- Browse existing BFF scripts
- Find reusable backend functions
- Confirm script ID before modification
2. get_bff_script_info - Get Script Details
Get complete information of BFF script by ID, including source code.
Parameters:
{
id: number; // BFF script ID (required)
appCode?: string; // Application code (optional)
cookie?: string; // Authentication cookie (optional)
}
Return Example:
{
"id": 123,
"name": "getUserInfo",
"description": "Get user detailed information",
"scriptContent": "export default async function(params, context) {\n const userId = params.userId;\n const user = await context.client.models.customer.getOne({ id: userId });\n return { success: true, data: user };\n}",
"scriptType": "ENDPOINT",
"createTime": "2026-03-20 10:30:00",
"updateTime": "2026-03-26 14:20:00",
"createUser": "user@example.com",
"updateUser": "user@example.com"
}
Use Cases:
- View existing code before modification
- Learn from other script implementations
- Debug problem scripts
3. save_or_update_bff_script - Save or Update Backend Function
Save new BFF script or update existing script.
Parameters:
{
id?: number; // Script ID (required for update, omit for new)
description: string; // Function description (required)
scriptContent: string; // JavaScript/TypeScript code (required)
appCode?: string; // Application code (optional)
cookie?: string; // Authentication cookie (optional)
}
Return Example (Success):
{
"success": true,
"id": 124,
"message": "BFF script saved successfully"
}
Return Example (Conflict):
{
"success": false,
"blocked": true,
"message": "Last submitter is other@example.com, please operate manually"
}
Important Mechanisms:
- Automatic Cache Clearing: Automatically call Runtime API to clear script cache after successful save
- Force Validation: Force validate dataset and field references before save
- Conflict Detection: Detect if last submitter is current user (see below)
- Block Mechanism: If returns
blocked: true, AI must not auto-retry
Conflict Detection Mechanism
4-Level Conflict Detection
When saving BFF script, MCP will detect conflicts through toolbox API:
| Level | Scenario | Risk | AI Behavior |
|---|---|---|---|
| NONE | New script | 🟢 None | Save directly |
| LOW | Own script | 🟢 Low | Allow save |
| HIGH | Others recently modified (less than 30 days) | 🔴 High | Block, prompt user |
| MEDIUM | Others earlier modified (more than 30 days) | 🟡 Medium | Block, prompt user |
Conflict Handling Flow
Save Request
│
├─ New → ✅ Save directly
│
└─ Update → Check last submitter
│
├─ Self → ✅ Allow save
│
└─ Others → Check time
│
├─ Less than 30 days → 🔴 blocked: true
│
└─ More than 30 days → 🟡 blocked: true
AI Behavior Guidelines
When returning blocked: true:
-
✅ Should Do:
- Inform user of conflict
- Prompt last submitter information
- Suggest user operate manually or coordinate
- Provide method to view existing code
-
❌ Must Not Do:
- Auto-retry save
- Ignore conflict warning
- Force overwrite others' code
Example Prompt:
⚠️ Conflict detected!
**Conflict Information**:
- Script ID: 123
- Last submitter: colleague@company.com
- Modified: 2 hours ago
**Suggested Actions**:
1. Coordinate with colleague@company.com
2. Or operate manually in platform interface
I will not automatically overwrite others' code.
BFF Code Writing Guidelines
Basic Structure
export default async function(params, context) {
// 1. Parameter validation
const userId = params.userId;
if (!userId) {
return { success: false, message: "userId is required" };
}
// 2. Data access (use context.client)
const user = await context.client.models.customer.getOne({
id: userId
});
// 3. Business logic
if (!user) {
return { success: false, message: "User not found" };
}
// 4. Return result
return {
success: true,
data: user
};
}
Two Runtime Contexts
1. Frontend SDK (Frontend)
// Returns wrapper
const data = await client.sql.execute({ sqlCode: 'xxx' });
if (!data.execSuccess) {
throw new Error('SQL execution failed');
}
const results = data.execResult || [];
2. Backend Function (Backend)
// Returns array directly, no wrapper
const rows = await context.client.sql.execute({ sqlCode: 'xxx' });
// rows is T[] type, errors throw exceptions directly
Important Differences:
- SQL Execution: BFF returns array
T[]directly, SDK returns{ execSuccess, execResult } - Error Handling: BFF errors throw exceptions, SDK returns
{ execSuccess: false } - Data Operations: Both call methods same, only return structure different
Usage Examples
Example 1: Create New BFF Script
User Request:
Create a BFF function to get user information and order count by user ID
AI Execution Steps:
- Generate code:
export default async function(params, context) {
const userId = params.userId;
if (!userId) {
return { success: false, message: "userId is required" };
}
// Get user information
const user = await context.client.models.customer.getOne({
id: userId
});
if (!user) {
return { success: false, message: "User not found" };
}
// Count orders
const orders = await context.client.models.order.filter({
where: { customer_id: { $eq: userId } },
select: ["id"]
});
return {
success: true,
data: {
user: user,
orderCount: orders.length
}
};
}
- Call
save_or_update_bff_script:
{
"description": "Get user information and order count by user ID",
"scriptContent": "export default async function(params, context) { ... }"
}
- Return result:
{
"success": true,
"id": 125,
"message": "BFF script saved successfully"
}
Example 2: Update Existing BFF Script (No Conflict)
User Request:
Modify BFF script #123, add error handling
AI Execution Steps:
- Call
get_bff_script_info({ id: 123 }) - Modify code (add try-catch)
- Call
save_or_update_bff_script:
{
"id": 123,
"description": "Get user detailed information (with error handling)",
"scriptContent": "export default async function(params, context) { try { ... } catch (error) { return { success: false, message: error.message }; } }"
}
Example 3: Update Existing BFF Script (With Conflict)
Scenario: Last submitter is colleague, modified 2 hours ago.
AI Execution Steps:
- Call
get_bff_script_info({ id: 123 }) - Modify code
- Call
save_or_update_bff_script - Returns
blocked: true:
{
"success": false,
"blocked": true,
"message": "Last submitter is colleague@company.com, please operate manually"
}
- AI Should Inform User:
⚠️ Conflict detected!
**Conflict Information**:
- Script ID: 123
- Last submitter: colleague@company.com
- Modified: 2 hours ago
**Suggested Actions**:
1. Coordinate with colleague@company.com
2. Or operate manually in platform interface
I will not automatically overwrite others' code.
Best Practices
1. Coding Standards
- ✅ Parameter validation at function start
- ✅ Use
context.clientfor data access - ✅ Unified return structure
{ success, data/message } - ✅ Add clear function description
- ✅ Handle all possible errors
2. Conflict Avoidance
- ✅ Call
get_bff_script_infoto view details before modification - ✅ Coordinate in advance for large modifications
- ✅ Use descriptive naming and comments
- ✅ Regularly clean up unused scripts
3. Performance Optimization
- ✅ Use
selectto query only necessary fields - ✅ Use
filterfor batch operations instead of loops - ✅ Avoid deep nested queries
- ✅ Reasonably use SQL queries
Security Recommendations
Production Environment
- Restrict Permissions: Only enable BFF save feature for those who need it
- Code Review: AI-generated BFF scripts should have manual review
- Backup Mechanism: Backup important scripts before modification
- Audit Logs: Regularly check BFF script modification history
Team Collaboration
- Coordination: Communicate before modifying others' scripts
- Version Control: Add version and modification records in scripts
- Audit Logs: Regularly view BFF script modification history
- Naming Conventions: Use clear naming conventions
Troubleshooting
Issue 1: BFF Tools Unavailable
Reason: --enable-bff-save parameter not enabled
Solution:
- Check MCP configuration file
- Confirm
argscontains--enable-bff-save - Restart MCP server
Issue 2: Save Returns blocked: true
Reason: Others have recently modified this script
Solution:
- View returned conflict information
- Communicate with last submitter
- Operate manually in platform interface
Issue 3: Script Cache Not Cleared
Reason: Cache automatically cleared after save, but there may be delay
Solution:
- Wait 1-2 minutes
- Clear browser cache
- Retry request
Related Documentation
- Tools Reference - Complete MCP tools list
- Configuration Guide - MCP configuration details
- SDK Usage Guide - SDK calling conventions
- Usage Examples - Real-world use cases
Last Updated: 2026-03-26 Version: v1.0