From eb49fb9a98d6dd4e4361daf4eac4f9313236b8e8 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 19 三月 2026 10:56:34 +0800
Subject: [PATCH] #AI多租户管控

---
 rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiParamController.java             |   34 +++++-
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiPromptServiceImpl.java         |   42 +++++++-
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java       |   47 ++++++--
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java          |   44 +++++++-
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiConfigResolverServiceImpl.java |   12 +
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java           |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiParamService.java                   |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiMcpMountController.java          |   34 +++++-
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiPromptService.java                  |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiPromptController.java            |   34 +++++-
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiMcpMountService.java                |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiConfigResolverService.java          |    2 
 12 files changed, 207 insertions(+), 66 deletions(-)

diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiMcpMountController.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiMcpMountController.java
index 57cf3ca..3525e6e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiMcpMountController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiMcpMountController.java
@@ -1,6 +1,7 @@
 package com.vincent.rsf.server.ai.controller;
 
 import com.vincent.rsf.framework.common.R;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.vincent.rsf.server.ai.dto.AiMcpToolTestRequest;
 import com.vincent.rsf.server.ai.entity.AiMcpMount;
 import com.vincent.rsf.server.ai.service.AiMcpMountService;
@@ -29,25 +30,38 @@
     public R page(@RequestBody Map<String, Object> map) {
         BaseParam baseParam = buildParam(map, BaseParam.class);
         PageParam<AiMcpMount, BaseParam> pageParam = new PageParam<>(baseParam, AiMcpMount.class);
-        return R.ok().add(aiMcpMountService.page(pageParam, pageParam.buildWrapper(true)));
+        return R.ok().add(aiMcpMountService.page(pageParam, pageParam.buildWrapper(true)
+                .eq("tenant_id", getTenantId())
+                .eq("deleted", 0)));
     }
 
     @PreAuthorize("hasAuthority('system:aiMcpMount:list')")
     @PostMapping("/aiMcpMount/list")
     public R list(@RequestBody Map<String, Object> map) {
-        return R.ok().add(aiMcpMountService.list());
+        return R.ok().add(aiMcpMountService.list(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getTenantId, getTenantId())
+                .eq(AiMcpMount::getDeleted, 0)
+                .orderByAsc(AiMcpMount::getSort)
+                .orderByDesc(AiMcpMount::getId)));
     }
 
     @PreAuthorize("hasAuthority('system:aiMcpMount:list')")
     @PostMapping({"/aiMcpMount/many/{ids}", "/aiMcpMounts/many/{ids}"})
     public R many(@PathVariable Long[] ids) {
-        return R.ok().add(aiMcpMountService.listByIds(Arrays.asList(ids)));
+        return R.ok().add(aiMcpMountService.list(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getTenantId, getTenantId())
+                .eq(AiMcpMount::getDeleted, 0)
+                .in(AiMcpMount::getId, Arrays.asList(ids))));
     }
 
     @PreAuthorize("hasAuthority('system:aiMcpMount:list')")
     @GetMapping("/aiMcpMount/{id}")
     public R get(@PathVariable("id") Long id) {
-        return R.ok().add(aiMcpMountService.getById(id));
+        return R.ok().add(aiMcpMountService.getOne(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getId, id)
+                .eq(AiMcpMount::getTenantId, getTenantId())
+                .eq(AiMcpMount::getDeleted, 0)
+                .last("limit 1")));
     }
 
     @PreAuthorize("hasAuthority('system:aiMcpMount:list')")
@@ -66,7 +80,8 @@
     @OperationLog("Create AiMcpMount")
     @PostMapping("/aiMcpMount/save")
     public R save(@RequestBody AiMcpMount aiMcpMount) {
-        aiMcpMountService.validateBeforeSave(aiMcpMount);
+        aiMcpMount.setTenantId(getTenantId());
+        aiMcpMountService.validateBeforeSave(aiMcpMount, getTenantId());
         aiMcpMount.setCreateBy(getLoginUserId());
         aiMcpMount.setCreateTime(new Date());
         aiMcpMount.setUpdateBy(getLoginUserId());
@@ -81,7 +96,8 @@
     @OperationLog("Update AiMcpMount")
     @PostMapping("/aiMcpMount/update")
     public R update(@RequestBody AiMcpMount aiMcpMount) {
-        aiMcpMountService.validateBeforeUpdate(aiMcpMount);
+        aiMcpMount.setTenantId(getTenantId());
+        aiMcpMountService.validateBeforeUpdate(aiMcpMount, getTenantId());
         aiMcpMount.setUpdateBy(getLoginUserId());
         aiMcpMount.setUpdateTime(new Date());
         if (!aiMcpMountService.updateById(aiMcpMount)) {
@@ -103,6 +119,10 @@
     @PreAuthorize("hasAuthority('system:aiMcpMount:list')")
     @PostMapping("/aiMcpMount/export")
     public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
-        ExcelUtil.build(ExcelUtil.create(aiMcpMountService.list(), AiMcpMount.class), response);
+        ExcelUtil.build(ExcelUtil.create(aiMcpMountService.list(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getTenantId, getTenantId())
+                .eq(AiMcpMount::getDeleted, 0)
+                .orderByAsc(AiMcpMount::getSort)
+                .orderByDesc(AiMcpMount::getId)), AiMcpMount.class), response);
     }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiParamController.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiParamController.java
index 8f1d8b7..874c315 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiParamController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiParamController.java
@@ -1,6 +1,7 @@
 package com.vincent.rsf.server.ai.controller;
 
 import com.vincent.rsf.framework.common.R;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.vincent.rsf.server.ai.entity.AiParam;
 import com.vincent.rsf.server.ai.service.AiParamService;
 import com.vincent.rsf.server.common.annotation.OperationLog;
@@ -28,32 +29,46 @@
     public R page(@RequestBody Map<String, Object> map) {
         BaseParam baseParam = buildParam(map, BaseParam.class);
         PageParam<AiParam, BaseParam> pageParam = new PageParam<>(baseParam, AiParam.class);
-        return R.ok().add(aiParamService.page(pageParam, pageParam.buildWrapper(true)));
+        return R.ok().add(aiParamService.page(pageParam, pageParam.buildWrapper(true)
+                .eq("tenant_id", getTenantId())
+                .eq("deleted", 0)));
     }
 
     @PreAuthorize("hasAuthority('system:aiParam:list')")
     @PostMapping("/aiParam/list")
     public R list(@RequestBody Map<String, Object> map) {
-        return R.ok().add(aiParamService.list());
+        return R.ok().add(aiParamService.list(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getTenantId, getTenantId())
+                .eq(AiParam::getDeleted, 0)
+                .orderByDesc(AiParam::getCreateTime)
+                .orderByDesc(AiParam::getId)));
     }
 
     @PreAuthorize("hasAuthority('system:aiParam:list')")
     @PostMapping({"/aiParam/many/{ids}", "/aiParams/many/{ids}"})
     public R many(@PathVariable Long[] ids) {
-        return R.ok().add(aiParamService.listByIds(Arrays.asList(ids)));
+        return R.ok().add(aiParamService.list(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getTenantId, getTenantId())
+                .eq(AiParam::getDeleted, 0)
+                .in(AiParam::getId, Arrays.asList(ids))));
     }
 
     @PreAuthorize("hasAuthority('system:aiParam:list')")
     @GetMapping("/aiParam/{id}")
     public R get(@PathVariable("id") Long id) {
-        return R.ok().add(aiParamService.getById(id));
+        return R.ok().add(aiParamService.getOne(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getId, id)
+                .eq(AiParam::getTenantId, getTenantId())
+                .eq(AiParam::getDeleted, 0)
+                .last("limit 1")));
     }
 
     @PreAuthorize("hasAuthority('system:aiParam:save')")
     @OperationLog("Create AiParam")
     @PostMapping("/aiParam/save")
     public R save(@RequestBody AiParam aiParam) {
-        aiParamService.validateBeforeSave(aiParam);
+        aiParam.setTenantId(getTenantId());
+        aiParamService.validateBeforeSave(aiParam, getTenantId());
         aiParam.setCreateBy(getLoginUserId());
         aiParam.setCreateTime(new Date());
         aiParam.setUpdateBy(getLoginUserId());
@@ -68,7 +83,8 @@
     @OperationLog("Update AiParam")
     @PostMapping("/aiParam/update")
     public R update(@RequestBody AiParam aiParam) {
-        aiParamService.validateBeforeUpdate(aiParam);
+        aiParam.setTenantId(getTenantId());
+        aiParamService.validateBeforeUpdate(aiParam, getTenantId());
         aiParam.setUpdateBy(getLoginUserId());
         aiParam.setUpdateTime(new Date());
         if (!aiParamService.updateById(aiParam)) {
@@ -90,6 +106,10 @@
     @PreAuthorize("hasAuthority('system:aiParam:list')")
     @PostMapping("/aiParam/export")
     public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
-        ExcelUtil.build(ExcelUtil.create(aiParamService.list(), AiParam.class), response);
+        ExcelUtil.build(ExcelUtil.create(aiParamService.list(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getTenantId, getTenantId())
+                .eq(AiParam::getDeleted, 0)
+                .orderByDesc(AiParam::getCreateTime)
+                .orderByDesc(AiParam::getId)), AiParam.class), response);
     }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiPromptController.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiPromptController.java
index 8c40c39..d35f879 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiPromptController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/controller/AiPromptController.java
@@ -1,6 +1,7 @@
 package com.vincent.rsf.server.ai.controller;
 
 import com.vincent.rsf.framework.common.R;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.vincent.rsf.server.ai.entity.AiPrompt;
 import com.vincent.rsf.server.ai.service.AiPromptService;
 import com.vincent.rsf.server.common.annotation.OperationLog;
@@ -28,32 +29,46 @@
     public R page(@RequestBody Map<String, Object> map) {
         BaseParam baseParam = buildParam(map, BaseParam.class);
         PageParam<AiPrompt, BaseParam> pageParam = new PageParam<>(baseParam, AiPrompt.class);
-        return R.ok().add(aiPromptService.page(pageParam, pageParam.buildWrapper(true)));
+        return R.ok().add(aiPromptService.page(pageParam, pageParam.buildWrapper(true)
+                .eq("tenant_id", getTenantId())
+                .eq("deleted", 0)));
     }
 
     @PreAuthorize("hasAuthority('system:aiPrompt:list')")
     @PostMapping("/aiPrompt/list")
     public R list(@RequestBody Map<String, Object> map) {
-        return R.ok().add(aiPromptService.list());
+        return R.ok().add(aiPromptService.list(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getTenantId, getTenantId())
+                .eq(AiPrompt::getDeleted, 0)
+                .orderByDesc(AiPrompt::getCreateTime)
+                .orderByDesc(AiPrompt::getId)));
     }
 
     @PreAuthorize("hasAuthority('system:aiPrompt:list')")
     @PostMapping({"/aiPrompt/many/{ids}", "/aiPrompts/many/{ids}"})
     public R many(@PathVariable Long[] ids) {
-        return R.ok().add(aiPromptService.listByIds(Arrays.asList(ids)));
+        return R.ok().add(aiPromptService.list(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getTenantId, getTenantId())
+                .eq(AiPrompt::getDeleted, 0)
+                .in(AiPrompt::getId, Arrays.asList(ids))));
     }
 
     @PreAuthorize("hasAuthority('system:aiPrompt:list')")
     @GetMapping("/aiPrompt/{id}")
     public R get(@PathVariable("id") Long id) {
-        return R.ok().add(aiPromptService.getById(id));
+        return R.ok().add(aiPromptService.getOne(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getId, id)
+                .eq(AiPrompt::getTenantId, getTenantId())
+                .eq(AiPrompt::getDeleted, 0)
+                .last("limit 1")));
     }
 
     @PreAuthorize("hasAuthority('system:aiPrompt:save')")
     @OperationLog("Create AiPrompt")
     @PostMapping("/aiPrompt/save")
     public R save(@RequestBody AiPrompt aiPrompt) {
-        aiPromptService.validateBeforeSave(aiPrompt);
+        aiPrompt.setTenantId(getTenantId());
+        aiPromptService.validateBeforeSave(aiPrompt, getTenantId());
         aiPrompt.setCreateBy(getLoginUserId());
         aiPrompt.setCreateTime(new Date());
         aiPrompt.setUpdateBy(getLoginUserId());
@@ -68,7 +83,8 @@
     @OperationLog("Update AiPrompt")
     @PostMapping("/aiPrompt/update")
     public R update(@RequestBody AiPrompt aiPrompt) {
-        aiPromptService.validateBeforeUpdate(aiPrompt);
+        aiPrompt.setTenantId(getTenantId());
+        aiPromptService.validateBeforeUpdate(aiPrompt, getTenantId());
         aiPrompt.setUpdateBy(getLoginUserId());
         aiPrompt.setUpdateTime(new Date());
         if (!aiPromptService.updateById(aiPrompt)) {
@@ -90,6 +106,10 @@
     @PreAuthorize("hasAuthority('system:aiPrompt:list')")
     @PostMapping("/aiPrompt/export")
     public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
-        ExcelUtil.build(ExcelUtil.create(aiPromptService.list(), AiPrompt.class), response);
+        ExcelUtil.build(ExcelUtil.create(aiPromptService.list(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getTenantId, getTenantId())
+                .eq(AiPrompt::getDeleted, 0)
+                .orderByDesc(AiPrompt::getCreateTime)
+                .orderByDesc(AiPrompt::getId)), AiPrompt.class), response);
     }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiConfigResolverService.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiConfigResolverService.java
index 23b125c..0f83417 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiConfigResolverService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiConfigResolverService.java
@@ -4,5 +4,5 @@
 
 public interface AiConfigResolverService {
 
-    AiResolvedConfig resolve(String promptCode);
+    AiResolvedConfig resolve(String promptCode, Long tenantId);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiMcpMountService.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiMcpMountService.java
index 79faeb5..efac400 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiMcpMountService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiMcpMountService.java
@@ -10,11 +10,11 @@
 
 public interface AiMcpMountService extends IService<AiMcpMount> {
 
-    List<AiMcpMount> listActiveMounts();
+    List<AiMcpMount> listActiveMounts(Long tenantId);
 
-    void validateBeforeSave(AiMcpMount aiMcpMount);
+    void validateBeforeSave(AiMcpMount aiMcpMount, Long tenantId);
 
-    void validateBeforeUpdate(AiMcpMount aiMcpMount);
+    void validateBeforeUpdate(AiMcpMount aiMcpMount, Long tenantId);
 
     List<AiMcpToolPreviewDto> previewTools(Long mountId, Long userId, Long tenantId);
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiParamService.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiParamService.java
index 9cd1f9e..b92b9b9 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiParamService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiParamService.java
@@ -5,9 +5,9 @@
 
 public interface AiParamService extends IService<AiParam> {
 
-    AiParam getActiveParam();
+    AiParam getActiveParam(Long tenantId);
 
-    void validateBeforeSave(AiParam aiParam);
+    void validateBeforeSave(AiParam aiParam, Long tenantId);
 
-    void validateBeforeUpdate(AiParam aiParam);
+    void validateBeforeUpdate(AiParam aiParam, Long tenantId);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiPromptService.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiPromptService.java
index f8a7913..ef449dc 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiPromptService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/AiPromptService.java
@@ -5,9 +5,9 @@
 
 public interface AiPromptService extends IService<AiPrompt> {
 
-    AiPrompt getActivePrompt(String code);
+    AiPrompt getActivePrompt(String code, Long tenantId);
 
-    void validateBeforeSave(AiPrompt aiPrompt);
+    void validateBeforeSave(AiPrompt aiPrompt, Long tenantId);
 
-    void validateBeforeUpdate(AiPrompt aiPrompt);
+    void validateBeforeUpdate(AiPrompt aiPrompt, Long tenantId);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
index 7fc31fc..5cb9552 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
@@ -72,7 +72,7 @@
 
     @Override
     public AiChatRuntimeDto getRuntime(String promptCode, Long sessionId, Long userId, Long tenantId) {
-        AiResolvedConfig config = aiConfigResolverService.resolve(promptCode);
+        AiResolvedConfig config = aiConfigResolverService.resolve(promptCode, tenantId);
         AiChatMemoryDto memory = aiChatMemoryService.getMemory(userId, tenantId, config.getPromptCode(), sessionId);
         return AiChatRuntimeDto.builder()
                 .sessionId(memory.getSessionId())
@@ -89,7 +89,7 @@
 
     @Override
     public List<AiChatSessionDto> listSessions(String promptCode, Long userId, Long tenantId) {
-        AiResolvedConfig config = aiConfigResolverService.resolve(promptCode);
+        AiResolvedConfig config = aiConfigResolverService.resolve(promptCode, tenantId);
         return aiChatMemoryService.listSessions(userId, tenantId, config.getPromptCode());
     }
 
@@ -107,7 +107,7 @@
 
     private void doStream(AiChatRequest request, Long userId, Long tenantId, SseEmitter emitter) {
         try {
-            AiResolvedConfig config = aiConfigResolverService.resolve(request.getPromptCode());
+            AiResolvedConfig config = aiConfigResolverService.resolve(request.getPromptCode(), tenantId);
             AiChatSession session = aiChatMemoryService.resolveSession(userId, tenantId, config.getPromptCode(), request.getSessionId(), resolveTitleSeed(request.getMessages()));
             AiChatMemoryDto memory = aiChatMemoryService.getMemory(userId, tenantId, config.getPromptCode(), session.getId());
             List<AiChatMessageDto> mergedMessages = mergeMessages(memory.getPersistedMessages(), request.getMessages());
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiConfigResolverServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiConfigResolverServiceImpl.java
index 366e1a9..991bfd2 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiConfigResolverServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiConfigResolverServiceImpl.java
@@ -6,6 +6,7 @@
 import com.vincent.rsf.server.ai.service.AiMcpMountService;
 import com.vincent.rsf.server.ai.service.AiParamService;
 import com.vincent.rsf.server.ai.service.AiPromptService;
+import com.vincent.rsf.framework.exception.CoolException;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
@@ -19,13 +20,16 @@
     private final AiMcpMountService aiMcpMountService;
 
     @Override
-    public AiResolvedConfig resolve(String promptCode) {
+    public AiResolvedConfig resolve(String promptCode, Long tenantId) {
+        if (tenantId == null) {
+            throw new CoolException("褰撳墠绉熸埛涓嶅瓨鍦�");
+        }
         String finalPromptCode = StringUtils.hasText(promptCode) ? promptCode : AiDefaults.DEFAULT_PROMPT_CODE;
         return AiResolvedConfig.builder()
                 .promptCode(finalPromptCode)
-                .aiParam(aiParamService.getActiveParam())
-                .prompt(aiPromptService.getActivePrompt(finalPromptCode))
-                .mcpMounts(aiMcpMountService.listActiveMounts())
+                .aiParam(aiParamService.getActiveParam(tenantId))
+                .prompt(aiPromptService.getActivePrompt(finalPromptCode, tenantId))
+                .mcpMounts(aiMcpMountService.listActiveMounts(tenantId))
                 .build();
     }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
index 822d55c..7221714 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
@@ -34,31 +34,39 @@
     private final ObjectMapper objectMapper;
 
     @Override
-    public List<AiMcpMount> listActiveMounts() {
+    public List<AiMcpMount> listActiveMounts(Long tenantId) {
+        ensureTenantId(tenantId);
         return this.list(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getTenantId, tenantId)
                 .eq(AiMcpMount::getStatus, StatusType.ENABLE.val)
+                .eq(AiMcpMount::getDeleted, 0)
                 .orderByAsc(AiMcpMount::getSort)
                 .orderByAsc(AiMcpMount::getId));
     }
 
     @Override
-    public void validateBeforeSave(AiMcpMount aiMcpMount) {
+    public void validateBeforeSave(AiMcpMount aiMcpMount, Long tenantId) {
+        ensureTenantId(tenantId);
+        aiMcpMount.setTenantId(tenantId);
         fillDefaults(aiMcpMount);
-        ensureRequiredFields(aiMcpMount);
+        ensureRequiredFields(aiMcpMount, tenantId);
     }
 
     @Override
-    public void validateBeforeUpdate(AiMcpMount aiMcpMount) {
+    public void validateBeforeUpdate(AiMcpMount aiMcpMount, Long tenantId) {
+        ensureTenantId(tenantId);
         fillDefaults(aiMcpMount);
         if (aiMcpMount.getId() == null) {
             throw new CoolException("MCP 鎸傝浇 ID 涓嶈兘涓虹┖");
         }
-        ensureRequiredFields(aiMcpMount);
+        AiMcpMount current = requireMount(aiMcpMount.getId(), tenantId);
+        aiMcpMount.setTenantId(current.getTenantId());
+        ensureRequiredFields(aiMcpMount, tenantId);
     }
 
     @Override
     public List<AiMcpToolPreviewDto> previewTools(Long mountId, Long userId, Long tenantId) {
-        AiMcpMount mount = requireMount(mountId);
+        AiMcpMount mount = requireMount(mountId, tenantId);
         try (McpMountRuntimeFactory.McpMountRuntime runtime = mcpMountRuntimeFactory.create(List.of(mount), userId)) {
             List<AiMcpToolPreviewDto> tools = new ArrayList<>();
             for (ToolCallback callback : runtime.getToolCallbacks()) {
@@ -98,7 +106,7 @@
         } catch (Exception e) {
             throw new CoolException("宸ュ叿杈撳叆 JSON 鏍煎紡閿欒: " + e.getMessage());
         }
-        AiMcpMount mount = requireMount(mountId);
+        AiMcpMount mount = requireMount(mountId, tenantId);
         try (McpMountRuntimeFactory.McpMountRuntime runtime = mcpMountRuntimeFactory.create(List.of(mount), userId)) {
             ToolCallback callback = Arrays.stream(runtime.getToolCallbacks())
                     .filter(item -> item != null && item.getToolDefinition() != null)
@@ -132,13 +140,13 @@
         }
     }
 
-    private void ensureRequiredFields(AiMcpMount aiMcpMount) {
+    private void ensureRequiredFields(AiMcpMount aiMcpMount, Long tenantId) {
         if (!StringUtils.hasText(aiMcpMount.getName())) {
             throw new CoolException("MCP 鎸傝浇鍚嶇О涓嶈兘涓虹┖");
         }
         if (AiDefaults.MCP_TRANSPORT_BUILTIN.equals(aiMcpMount.getTransportType())) {
             builtinMcpToolRegistry.validateBuiltinCode(aiMcpMount.getBuiltinCode());
-            ensureBuiltinConflictFree(aiMcpMount);
+            ensureBuiltinConflictFree(aiMcpMount, tenantId);
             return;
         }
         if (AiDefaults.MCP_TRANSPORT_SSE_HTTP.equals(aiMcpMount.getTransportType())) {
@@ -156,18 +164,23 @@
         throw new CoolException("涓嶆敮鎸佺殑 MCP 浼犺緭绫诲瀷: " + aiMcpMount.getTransportType());
     }
 
-    private AiMcpMount requireMount(Long mountId) {
+    private AiMcpMount requireMount(Long mountId, Long tenantId) {
+        ensureTenantId(tenantId);
         if (mountId == null) {
             throw new CoolException("MCP 鎸傝浇 ID 涓嶈兘涓虹┖");
         }
-        AiMcpMount mount = this.getById(mountId);
-        if (mount == null || (mount.getDeleted() != null && mount.getDeleted() == 1)) {
+        AiMcpMount mount = this.getOne(new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getId, mountId)
+                .eq(AiMcpMount::getTenantId, tenantId)
+                .eq(AiMcpMount::getDeleted, 0)
+                .last("limit 1"));
+        if (mount == null) {
             throw new CoolException("MCP 鎸傝浇涓嶅瓨鍦�");
         }
         return mount;
     }
 
-    private void ensureBuiltinConflictFree(AiMcpMount aiMcpMount) {
+    private void ensureBuiltinConflictFree(AiMcpMount aiMcpMount, Long tenantId) {
         if (aiMcpMount.getStatus() == null || aiMcpMount.getStatus() != StatusType.ENABLE.val) {
             return;
         }
@@ -176,8 +189,10 @@
             return;
         }
         LambdaQueryWrapper<AiMcpMount> queryWrapper = new LambdaQueryWrapper<AiMcpMount>()
+                .eq(AiMcpMount::getTenantId, tenantId)
                 .eq(AiMcpMount::getTransportType, AiDefaults.MCP_TRANSPORT_BUILTIN)
                 .eq(AiMcpMount::getStatus, StatusType.ENABLE.val)
+                .eq(AiMcpMount::getDeleted, 0)
                 .in(AiMcpMount::getBuiltinCode, conflictCodes);
         if (aiMcpMount.getId() != null) {
             queryWrapper.ne(AiMcpMount::getId, aiMcpMount.getId());
@@ -205,4 +220,10 @@
         }
         return codes;
     }
+
+    private void ensureTenantId(Long tenantId) {
+        if (tenantId == null) {
+            throw new CoolException("褰撳墠绉熸埛涓嶅瓨鍦�");
+        }
+    }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
index 41a014b..07715d5 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
@@ -15,9 +15,12 @@
 public class AiParamServiceImpl extends ServiceImpl<AiParamMapper, AiParam> implements AiParamService {
 
     @Override
-    public AiParam getActiveParam() {
+    public AiParam getActiveParam(Long tenantId) {
+        ensureTenantId(tenantId);
         AiParam aiParam = this.getOne(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getTenantId, tenantId)
                 .eq(AiParam::getStatus, StatusType.ENABLE.val)
+                .eq(AiParam::getDeleted, 0)
                 .last("limit 1"));
         if (aiParam == null) {
             throw new CoolException("鏈壘鍒板惎鐢ㄤ腑鐨� AI 鍙傛暟閰嶇疆");
@@ -26,20 +29,25 @@
     }
 
     @Override
-    public void validateBeforeSave(AiParam aiParam) {
+    public void validateBeforeSave(AiParam aiParam, Long tenantId) {
+        ensureTenantId(tenantId);
+        aiParam.setTenantId(tenantId);
         fillDefaults(aiParam);
         ensureBaseFields(aiParam);
-        ensureSingleActive(aiParam, null);
+        ensureSingleActive(tenantId, null, aiParam.getStatus());
     }
 
     @Override
-    public void validateBeforeUpdate(AiParam aiParam) {
+    public void validateBeforeUpdate(AiParam aiParam, Long tenantId) {
+        ensureTenantId(tenantId);
         fillDefaults(aiParam);
         if (aiParam.getId() == null) {
             throw new CoolException("AI 鍙傛暟 ID 涓嶈兘涓虹┖");
         }
+        AiParam current = requireOwnedRecord(aiParam.getId(), tenantId);
+        aiParam.setTenantId(current.getTenantId());
         ensureBaseFields(aiParam);
-        ensureSingleActive(aiParam, aiParam.getId());
+        ensureSingleActive(tenantId, aiParam.getId(), aiParam.getStatus());
     }
 
     private void ensureBaseFields(AiParam aiParam) {
@@ -60,12 +68,14 @@
         }
     }
 
-    private void ensureSingleActive(AiParam aiParam, Long selfId) {
-        if (aiParam.getStatus() == null || aiParam.getStatus() != StatusType.ENABLE.val) {
+    private void ensureSingleActive(Long tenantId, Long selfId, Integer status) {
+        if (status == null || status != StatusType.ENABLE.val) {
             return;
         }
         LambdaQueryWrapper<AiParam> wrapper = new LambdaQueryWrapper<AiParam>()
-                .eq(AiParam::getStatus, StatusType.ENABLE.val);
+                .eq(AiParam::getTenantId, tenantId)
+                .eq(AiParam::getStatus, StatusType.ENABLE.val)
+                .eq(AiParam::getDeleted, 0);
         if (selfId != null) {
             wrapper.ne(AiParam::getId, selfId);
         }
@@ -74,6 +84,24 @@
         }
     }
 
+    private AiParam requireOwnedRecord(Long id, Long tenantId) {
+        AiParam aiParam = this.getOne(new LambdaQueryWrapper<AiParam>()
+                .eq(AiParam::getId, id)
+                .eq(AiParam::getTenantId, tenantId)
+                .eq(AiParam::getDeleted, 0)
+                .last("limit 1"));
+        if (aiParam == null) {
+            throw new CoolException("AI 鍙傛暟涓嶅瓨鍦ㄦ垨鏃犳潈璁块棶");
+        }
+        return aiParam;
+    }
+
+    private void ensureTenantId(Long tenantId) {
+        if (tenantId == null) {
+            throw new CoolException("褰撳墠绉熸埛涓嶅瓨鍦�");
+        }
+    }
+
     private void fillDefaults(AiParam aiParam) {
         if (!StringUtils.hasText(aiParam.getProviderType())) {
             aiParam.setProviderType(AiDefaults.PROVIDER_OPENAI_COMPATIBLE);
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiPromptServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiPromptServiceImpl.java
index 7603c97..b969e4e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiPromptServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiPromptServiceImpl.java
@@ -14,10 +14,13 @@
 public class AiPromptServiceImpl extends ServiceImpl<AiPromptMapper, AiPrompt> implements AiPromptService {
 
     @Override
-    public AiPrompt getActivePrompt(String code) {
+    public AiPrompt getActivePrompt(String code, Long tenantId) {
+        ensureTenantId(tenantId);
         AiPrompt aiPrompt = this.getOne(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getTenantId, tenantId)
                 .eq(AiPrompt::getCode, code)
                 .eq(AiPrompt::getStatus, StatusType.ENABLE.val)
+                .eq(AiPrompt::getDeleted, 0)
                 .last("limit 1"));
         if (aiPrompt == null) {
             throw new CoolException("鏈壘鍒板惎鐢ㄤ腑鐨� Prompt锛�" + code);
@@ -26,18 +29,23 @@
     }
 
     @Override
-    public void validateBeforeSave(AiPrompt aiPrompt) {
+    public void validateBeforeSave(AiPrompt aiPrompt, Long tenantId) {
+        ensureTenantId(tenantId);
+        aiPrompt.setTenantId(tenantId);
         ensureRequiredFields(aiPrompt);
-        ensureUniqueCode(aiPrompt.getCode(), null);
+        ensureUniqueCode(aiPrompt.getCode(), tenantId, null);
     }
 
     @Override
-    public void validateBeforeUpdate(AiPrompt aiPrompt) {
+    public void validateBeforeUpdate(AiPrompt aiPrompt, Long tenantId) {
+        ensureTenantId(tenantId);
         if (aiPrompt.getId() == null) {
             throw new CoolException("Prompt ID 涓嶈兘涓虹┖");
         }
+        AiPrompt current = requireOwnedRecord(aiPrompt.getId(), tenantId);
+        aiPrompt.setTenantId(current.getTenantId());
         ensureRequiredFields(aiPrompt);
-        ensureUniqueCode(aiPrompt.getCode(), aiPrompt.getId());
+        ensureUniqueCode(aiPrompt.getCode(), tenantId, aiPrompt.getId());
     }
 
     private void ensureRequiredFields(AiPrompt aiPrompt) {
@@ -55,9 +63,11 @@
         }
     }
 
-    private void ensureUniqueCode(String code, Long selfId) {
+    private void ensureUniqueCode(String code, Long tenantId, Long selfId) {
         LambdaQueryWrapper<AiPrompt> wrapper = new LambdaQueryWrapper<AiPrompt>()
-                .eq(AiPrompt::getCode, code);
+                .eq(AiPrompt::getTenantId, tenantId)
+                .eq(AiPrompt::getCode, code)
+                .eq(AiPrompt::getDeleted, 0);
         if (selfId != null) {
             wrapper.ne(AiPrompt::getId, selfId);
         }
@@ -65,4 +75,22 @@
             throw new CoolException("Prompt 缂栫爜宸插瓨鍦�");
         }
     }
+
+    private AiPrompt requireOwnedRecord(Long id, Long tenantId) {
+        AiPrompt aiPrompt = this.getOne(new LambdaQueryWrapper<AiPrompt>()
+                .eq(AiPrompt::getId, id)
+                .eq(AiPrompt::getTenantId, tenantId)
+                .eq(AiPrompt::getDeleted, 0)
+                .last("limit 1"));
+        if (aiPrompt == null) {
+            throw new CoolException("Prompt 涓嶅瓨鍦ㄦ垨鏃犳潈璁块棶");
+        }
+        return aiPrompt;
+    }
+
+    private void ensureTenantId(Long tenantId) {
+        if (tenantId == null) {
+            throw new CoolException("褰撳墠绉熸埛涓嶅瓨鍦�");
+        }
+    }
 }

--
Gitblit v1.9.1