Skip to content

Commit 1cd9b9f

Browse files
authored
Merge branch 'main' into feature_add_configurable_toolset
2 parents 22a6f85 + 4af34cd commit 1cd9b9f

File tree

28 files changed

+759
-195
lines changed

28 files changed

+759
-195
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Add the following configuration to the MCP client configuration file:
9898
```
9999

100100
## Components
101-
### Tools
101+
### OpenAPI Tools
102102
* `add_tags_to_db_instance`: Add tags to an RDS instance.
103103
* `allocate_instance_public_connection`: Allocate a public connection for an RDS instance.
104104
* `attach_whitelist_template_to_instance`: Attach a whitelist template to an RDS instance.
@@ -128,6 +128,11 @@ Add the following configuration to the MCP client configuration file:
128128
* `modify_db_instance_spec`: Modify RDS instance specifications.
129129
* `modify_parameter`: Modify RDS instance parameters.
130130
* `restart_db_instance`: Restart an RDS instance.
131+
### SQL Tools
132+
> The MCP Server will automatically create a read-only account, execute the SQL statement, and then automatically delete the account. This process requires that the MCP Server can connect to the instance.
133+
134+
* `show_engine_innodb_status`: Execute sql `show engine innodb status` and return sql result.
135+
* `show_create_table`: Execute sql `show create table` and return sql result.
131136

132137
### Toolsets
133138

README_CN.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ git clone https://github.com/aliyun/alibabacloud-rds-openapi-mcp-server.git
9898
```
9999

100100
## 功能组件
101-
### 工具集
101+
### OpenAPI 工具集
102102
* `add_tags_to_db_instance`: 添加标签到RDS实例
103103
* `allocate_instance_public_connection`: 为RDS实例分配公网连接
104104
* `attach_whitelist_template_to_instance`: 将白名单模板绑定到RDS实例
@@ -129,6 +129,7 @@ git clone https://github.com/aliyun/alibabacloud-rds-openapi-mcp-server.git
129129
* `modify_parameter`: 修改RDS实例参数
130130
* `restart_db_instance`: 重启RDS实例
131131

132+
132133
#### 工具集分组
133134

134135
工具集将可用的 MCP 工具进行分组管理,让你只启用需要的功能。启动服务器时可通过以下方式配置工具集:
@@ -157,6 +158,13 @@ export MCP_TOOLSETS=rds,rds_mssql_custom
157158
#### 默认行为
158159
如果未指定工具集,将自动加载默认的 `rds` 工具组。
159160

161+
### SQL 工具集
162+
> MCP Server会自动创建一个只读账号,执行SQL后再自动删除。需要MCP Server能够连通到实例。
163+
164+
* `show_engine_innodb_status`: Execute sql `show engine innodb status` and return sql result.
165+
* `show_create_table`: Execute sql `show create table` and return sql result.
166+
167+
160168
### 资源
161169
当前暂无资源
162170

component/mydba/README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,15 @@ uv sync --inexact
7777
data_dir = /usr/local/mydba/vector_store
7878
```
7979

80-
2. **Initialize Agent**
80+
2. **Create Log Directory**
81+
- The log directory can be found in the configuration: [log].dir
82+
- Default path: /usr/local/mydba/logs
83+
84+
```shell
85+
mkdir /usr/local/mydba/logs
86+
```
87+
88+
3. **Initialize Agent**
8189
- Execute the following command to initialize the Agent. Ensure you have correctly configured the **`config_app.ini`** file and replace `xxxxxx` with your Alibaba Cloud account AK/SK.
8290

8391
```shell
@@ -90,7 +98,7 @@ uv sync --inexact
9098
--rds_access_key xxxxxx # Replace with your Alicloud account secret
9199
```
92100

93-
3. **Add Self-Built Database**
101+
4. **Add Self-Built Database**
94102
- Execute the following command to add a self-built database. Ensure you have correctly configured the **`config_app.ini`** file and replace `--db_info` parameters with actual database connection details.
95103

96104
```shell
@@ -101,7 +109,7 @@ uv sync --inexact
101109
--db_info 'mysql####127.0.0.1##3306##root##123456##utf8mb4##mybase' # Database connection info, pay attention to the escape of special characters
102110
```
103111

104-
4. **Initialize RAG Tool**
112+
5. **Initialize RAG Tool**
105113
- Execute the following command to initialize the RAG tool. Ensure you have correctly configured the **`config_app.ini`** file and added the **self-built database**.
106114

107115
```shell
@@ -138,4 +146,4 @@ uv sync --inexact
138146

139147
## Contact Us
140148

141-
- Welcome joining the DingTalk group for feedback, refer to the README.md of RDS MCP for details.
149+
- Welcome joining the DingTalk group for feedback, refer to the <a href="../../README.md">README.md</a> of RDS MCP for details.

component/mydba/README_CN.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,15 @@ uv sync --inexact
7676
data_dir = /usr/local/mydba/vector_store
7777
```
7878

79-
2. **初始化 Agent**
79+
2. **创建日志目录**
80+
- 日志目录可以查看配置: [log].dir
81+
- 默认路径:`/usr/local/mydba/logs`
82+
83+
```shell
84+
mkdir /usr/local/mydba/logs
85+
```
86+
87+
3. **初始化 Agent**
8088
- 执行以下命令以初始化 Agent。请确保您已经正确配置了 **`config_app.ini`** 文件,并用您的阿里云账号替换 `xxxxxx`
8189

8290
```shell
@@ -89,7 +97,7 @@ uv sync --inexact
8997
--rds_access_key xxxxxx # 替换为您的阿里云账号密钥
9098
```
9199

92-
3. **添加自建数据库**
100+
4. **添加自建数据库**
93101
- 执行以下命令以添加自建数据库。请确保您已正确配置 **`config_app.ini`** 文件,并根据实际情况替换 `--db_info` 参数中的数据库连接信息。
94102

95103
```shell
@@ -100,7 +108,7 @@ uv sync --inexact
100108
--db_info 'mysql####127.0.0.1##3306##root##123456##utf8mb4##mybase' # 数据库连接信息,注意特殊字符的转义
101109
```
102110

103-
4. **初始化 RAG 工具**
111+
5. **初始化 RAG 工具**
104112
- 执行以下命令以初始化 RAG 工具。请确保您已经正确配置了 **`config_app.ini`** 文件,并添加了**自建数据库**
105113

106114
```shell
@@ -137,4 +145,4 @@ uv sync --inexact
137145

138146
## 联系我们
139147

140-
- 向上查看 RDS MCP 的 README.md,加入钉钉群。
148+
- 向上查看 RDS MCP 的 <a href="../../README_CN.md">README_CN.md</a>,加入钉钉群。

component/mydba/init_config.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,52 @@
1414
from mydba.app.config.mcp_tool import Transport
1515
from mydba.app.config.settings import settings as app_settings
1616
from mydba.app.database.base_database import BaseDatabases
17-
from mydba.app.prompt import ask_table, reflection, router, using_tool
17+
from mydba.app.prompt import ask_table, chat, rds_agent, reflection, router
1818
from mydba.common import encryption
1919
from mydba.common.global_settings import global_settings
2020

2121
def get_agent_config() -> List[Dict]:
22-
"""获取 agent 的配置信息,**编辑此部分内容,定制 agent**"""
22+
"""
23+
获取 agent 的配置信息,**编辑此部分内容,定制 agent**<br/>
24+
配置项中,prompts 为提示词模版,包含字段:
25+
1) system: 系统提示词模版,
26+
2) user: 用户提示词模版,在需要改写用户提示词的场景下使用,例如:REFLECTION 模式、ROUTER 模式,
27+
3) reflection_system: 反思提示词模版,仅在 REFLECTION 模式下使用,
28+
4) reflection_user: 反思提示词模版,仅在 REFLECTION 模式下使用,
29+
5) condition: 条件提示词(List),在意图识别时,描述意图的约束条件,
30+
6) shot: 样本提示词(List),在意图识别时,提供意图样本
31+
Returns:
32+
List[Dict]: Agent 的配置信息列表
33+
"""
2334
main_agent = {
2435
"name": "main_agent",
2536
"mode": AgentMode.ROUTER,
2637
"intent": "识别意图",
2738
"intent_description": "识别用户的意图,并路由请求到相关 Agent",
2839
"prompts": {
40+
# 系统提示词模版
2941
"system": router.SYSTEM_PROMPT,
30-
"act": router.ACT_PROMPT
42+
# 用户提示词模版,意图识别时会改写用户指令
43+
"user": router.USER_PROMPT
3144
},
3245
"is_main": True,
3346
"is_default": False
3447
}
35-
rds_agent = {
48+
rds_agent_ = {
3649
"name": "rds_agent",
3750
"mode": AgentMode.USING_TOOL,
3851
"intent": "阿里云RDS管理",
3952
"intent_description": "进行阿里云 RDS 数据库的管理运维,或者对阿里云 RDS 数据库进行问题诊断",
4053
"prompts": {
41-
"system": using_tool.SYSTEM_PROMPT,
54+
# 系统提示词模版
55+
"system": rds_agent.SYSTEM_PROMPT,
56+
# 相关的意图约束条件,集成进意图识别提示词里,用于提升意图识别的准确度
4257
"condition":
4358
[
4459
"用户明确希望进行阿里云 RDS 数据库相关的操作时,才能归类到阿里云RDS管理",
4560
"用户希望对阿里云 RDS 数据库进行问题诊断时,才能归类到阿里云RDS管理"
4661
],
62+
# 相关的意图样例,集成进意图识别提示词里,用于提升意图识别的准确度
4763
"shot":
4864
[
4965
"查下张北有多少RDS实例",
@@ -63,11 +79,14 @@ def get_agent_config() -> List[Dict]:
6379
"intent": "数据查询",
6480
"intent_description": "帮助生成查询计划,执行数据库查询,最后完成数据的统计和分析",
6581
"prompts": {
82+
# 系统提示词模版
6683
"system": ask_table.SYSTEM_PROMPT,
84+
# 相关的意图约束条件,集成进意图识别提示词里,用于提升意图识别的准确度
6785
"condition":
6886
[
6987
"用户希望进行数据计算和统计时,要归类到数据查询"
7088
],
89+
# 相关的意图样例,集成进意图识别提示词里,用于提升意图识别的准确度
7190
"shot":
7291
[
7392
"查询集群信息"
@@ -83,19 +102,20 @@ def get_agent_config() -> List[Dict]:
83102
}
84103
default_agent = {
85104
"name": "default_agent",
86-
"mode": AgentMode.REFLECTION,
105+
"mode": AgentMode.CHAT,
87106
"intent": "默认",
88107
"intent_description": "无法匹配用户意图,使用此默认项",
89-
"prompts": {"system": reflection.SYSTEM_PROMPT, "act": reflection.ACT_PROMPT, "reflection": reflection.REFLECTION_PROMPT},
108+
"prompts": {"system": chat.SYSTEM_PROMPT},
90109
"is_main": False,
91110
"is_default": True
92111
}
93-
agents = [main_agent, rds_agent, ask_table_agent, default_agent]
112+
agents = [main_agent, rds_agent_, ask_table_agent, default_agent]
94113
return agents
95114

96115
def get_mcp_config() -> List[Dict]:
97116
"""获取 mcp 服务的配置信息,**编辑此部分内容,添加工具**"""
98-
base_dir = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + 'mydba' + os.path.sep + 'mcp'
117+
# 目前 RDS MCP 采用代码的相对路径进行配置,如果不符合请手动调整
118+
base_dir = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + '..' + os.path.sep + '..' + os.path.sep + '..'
99119
aliyun_rds_dir = os.path.join(base_dir, 'alibabacloud-rds-openapi-mcp-server', 'src', 'alibabacloud_rds_openapi_mcp_server')
100120
mcp_aliyun_rds = {
101121
"name": "rds-openapi-mcp-server",
@@ -463,10 +483,10 @@ def print_args(args: Namespace) -> None:
463483
for key, value in args.__dict__.items():
464484
# 过滤敏感信息
465485
if key.startswith('rds_access'):
466-
value = '******' if value else value
486+
value = mask_info(value)
467487
if key == 'db_info':
468488
v = value.split('##')
469-
v[5] = '******' if v[5] else v[5]
489+
v[5] = mask_info(v[5])
470490
value = '##'.join(v)
471491
# 打印参数
472492
if isinstance(value, str):
@@ -478,6 +498,13 @@ def print_args(args: Namespace) -> None:
478498
else:
479499
print(f" {key}: {value}")
480500

501+
def mask_info(info: Optional[str]) -> Optional[str]:
502+
if not info:
503+
return info
504+
if len(info) > 4:
505+
return info[:2] + '*' * (len(info) - 4) + info[-2:]
506+
return info[:1]+ "**"
507+
481508
if __name__ == "__main__":
482509
args = parse_arguments()
483510
print_args(args)

component/mydba/mydba/app/agent/base.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from mydba.app.message import memory_history
1010
from mydba.app.message.message import Message, ToolCall
1111
from mydba.app.message.memory_history import MemoryInfo
12-
from mydba.common.session import request_context
12+
from mydba.common.session import get_context
1313

1414
def cleanup_decorator(func):
1515
def wrapper(self, *args, **kwargs):
@@ -30,7 +30,7 @@ class BaseAgent(ABC, BaseModel):
3030
intent_description: Optional[str] = Field(None, description="意图描述")
3131
is_main: bool = Field(..., description="是否主 Agent")
3232
memory: List[Message] = Field(default_factory=list, description="本次处理过程中的短期记忆")
33-
prompt_patterns: Dict[str, str] = Field(default_factory=dict)
33+
prompt_patterns: Dict[str, str] = Field(default_factory=dict, description="提示词模版,不同类型的 Agent 依赖的提示词模版会有不同")
3434
llm: LLM = Field(..., description="LLM 实例")
3535

3636
@abstractmethod
@@ -51,7 +51,7 @@ async def get_history_memory(self) -> List[MemoryInfo]:
5151
Returns:
5252
list: Agent 的历史 memory。
5353
"""
54-
context = request_context.get()
54+
context = get_context()
5555
start_time = datetime.now() - timedelta(minutes=30)
5656
context_memory = await memory_history.get_memory(user_name=context.user_name, session=context.session,
5757
agent_name=self.name, start_time=start_time)
@@ -72,7 +72,7 @@ async def save_memory_history(self,
7272
assistant_tool_calls (List[ToolCall]): 大模型返回的工具调用。
7373
tool_contents (List[Dict[str, str]): 工具调用的结果,结果信息的格式为 {"tool_call_id": "xxx", "content": "xxx"}。
7474
"""
75-
context = request_context.get()
75+
context = get_context()
7676
await memory_history.save_memory(
7777
MemoryInfo(
7878
time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
@@ -120,10 +120,12 @@ def create_agent(agent_info: AgentInfo, llm: LLM) -> "BaseAgent":
120120
Returns:
121121
BaseAgent: Agent 实例
122122
"""
123+
from mydba.app.agent.chat import ChatAgent
123124
from mydba.app.agent.router import RouterAgent
124125
from mydba.app.agent.reflection import ReflectionAgent
125126
from mydba.app.agent.using_tool import UsingToolAgent
126127
agent_factory = {
128+
AgentMode.CHAT.value: ChatAgent,
127129
AgentMode.ROUTER.value: RouterAgent,
128130
AgentMode.REFLECTION.value: ReflectionAgent,
129131
AgentMode.USING_TOOL.value: UsingToolAgent,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# -*- coding: utf-8 -*-
2+
from pydantic import BaseModel, Field
3+
from typing import List, Optional
4+
from mydba.app.agent.base import BaseAgent, cleanup_decorator
5+
from mydba.app.message.memory_history import MemoryInfo
6+
from mydba.app.message.message import Message
7+
from mydba.common.logger import logger
8+
from mydba.common.session import get_context
9+
10+
class ChatAgent(BaseAgent, BaseModel):
11+
"""
12+
普通对话型 Agent
13+
"""
14+
system_message: Optional[Message] = Field(None, description="对话 Agent 的系统提示信息")
15+
16+
def __init__(self, **data):
17+
super().__init__(**data)
18+
prompts = data.get("prompts", {})
19+
self.prompt_patterns["system"] = prompts.get("system")
20+
self.system_message = Message.system_message(self.prompt_patterns["system"])
21+
22+
@cleanup_decorator
23+
async def run(self, query: str, context_memory: Optional[List[MemoryInfo]] = None) -> str:
24+
logger.info(f"[{self.name}] start to query: {query}")
25+
content = await self._execute_model(query, context_memory)
26+
if content is None:
27+
logger.error(f"[{self.name}] query model failed, query: {query}")
28+
raise Exception(f"Agent({self.name}) query model failed, query: {query}")
29+
#logger.info(f"[{self.name}] query over, result: {content}")
30+
await self.save_memory_history(system_content=self.system_message.content,
31+
user_content=query, assistant_content=content)
32+
return content
33+
34+
async def _execute_model(self, query: str, context_memory: Optional[List[MemoryInfo]]) -> str:
35+
context = get_context()
36+
messages = self.format_memory(context_memory) if context_memory else []
37+
messages.append(Message.user_message(query))
38+
result = await self.llm.ask(
39+
messages=messages,
40+
system_msgs=[self.system_message],
41+
stream=context.detail_info,
42+
)
43+
return result

0 commit comments

Comments
 (0)