mm-qa-mcp 1.0.0__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
minimax_qa_mcp/server.py CHANGED
@@ -19,7 +19,7 @@ from minimax_qa_mcp.src.get_weaviate_info.get_weaviate_info import GetWeaviateIn
19
19
  from minimax_qa_mcp.src.grafana.service import GetFromGrafana, GetApiFromGrafana
20
20
  from minimax_qa_mcp.src.gateway_case.get_case import CaseGrafanaService
21
21
  from minimax_qa_mcp.src.query_segments.query_segments import query_main, TYPE_API, TYPE_FUNC, TYPE_CODE, TYPE_ANY, TYPE_FUNC_DETAIL
22
-
22
+ from minimax_qa_mcp.src.get_full_api_call_chain.get_full_api_call_chain import GetFullApiCallChain
23
23
 
24
24
  # Initialize FastMCP server
25
25
  mcp = FastMCP("mcp")
@@ -162,6 +162,23 @@ async def get_weaviate_info(input_data: str) -> dict:
162
162
  return result
163
163
 
164
164
 
165
+ @mcp.tool()
166
+ async def get_full_api_call_chain(api_path: str) -> dict:
167
+ """
168
+ 获取API调用链
169
+ Args:
170
+ api_path: str,API路径(demo:/weaver/api/v1/ugc/get_npc_list_by_user_id)
171
+ Return:
172
+ API调用链信息
173
+ """
174
+ logger.info(f"===== The input params is :{api_path}")
175
+
176
+ api_call_chain = GetFullApiCallChain(api_path)
177
+ result = api_call_chain.get_full_call_chain()
178
+ logger.info(f"===== The result of get_full_api_call_chain is :{result}")
179
+ return result
180
+
181
+
165
182
  def main():
166
183
  print("Starting Minimax QA MCP server")
167
184
  """Run the Minimax QA MCP server"""
@@ -1,6 +1,6 @@
1
1
  """
2
2
  coding:utf-8
3
3
  @Software: PyCharm
4
- @Time: 2025/4/10 15:12
4
+ @Time: 2025/6/8 14:37
5
5
  @Author: xingyun
6
6
  """
@@ -0,0 +1,291 @@
1
+ """
2
+ coding:utf-8
3
+ @Software: PyCharm
4
+ @Time: 2025/6/8 14:37
5
+ @Author: xingyun
6
+ @description:
7
+ 根据api_path 获取完整的API调用链
8
+ 输入:api_path
9
+ 输出:完整的API调用链(包括所有下游调用)
10
+ """
11
+
12
+
13
+ from minimax_qa_mcp.utils.mysql_op import MysqlOp
14
+ from minimax_qa_mcp.utils.logger import logger
15
+
16
+ default_service = "weaver.gateway.weaver"
17
+
18
+
19
+ class GetFullApiCallChain:
20
+ def __init__(self, api_path):
21
+ """
22
+ 初始化调用链获取类
23
+ :param api_path: /path/to/endpoint (HTTP路径格式)
24
+ """
25
+ self.api_path = api_path
26
+ self.mysql_op = MysqlOp()
27
+ # API路径,获取服务名和方法名
28
+ self.caller_service = default_service
29
+ self.caller_method = api_path
30
+ # 存储已访问的调用路径,避免循环调用
31
+ self.visited_paths = set()
32
+ # 存储最终的调用链结果
33
+ self.call_chain_results = []
34
+
35
+ def get_downstream_calls(self, service, method):
36
+ """
37
+ 获取指定服务和方法的所有下游调用
38
+ :param service: 服务名称
39
+ :param method: 方法名称
40
+ :return: 下游调用列表
41
+ """
42
+ sql = """
43
+ SELECT caller_service, caller_method, callee_service, callee_method, call_type, code_chain
44
+ FROM qa_tools.code_call_chain
45
+ WHERE caller_service = %s AND caller_method = %s
46
+ """
47
+
48
+ result = self.mysql_op.connect(sql_=sql, data=(service, method), op='select')
49
+ return result if result else []
50
+
51
+ def _build_call_path(self, call_record, level=0, path=None):
52
+ """
53
+ 递归构建调用路径
54
+ :param call_record: 当前调用记录
55
+ :param level: 当前调用层级
56
+ :param path: 当前已构建的路径
57
+ :return: 构建完成的调用路径
58
+ """
59
+ caller_service = call_record[0]
60
+ caller_method = call_record[1]
61
+ callee_service = call_record[2]
62
+ callee_method = call_record[3]
63
+ call_type = call_record[4]
64
+
65
+ # 构建调用路径标识
66
+ call_id = f"{caller_service}.{caller_method} -> {callee_service}.{callee_method}"
67
+
68
+ # 检查是否已经访问过该路径,避免循环调用
69
+ if call_id in self.visited_paths:
70
+ return
71
+
72
+ self.visited_paths.add(call_id)
73
+
74
+ # 初始化路径
75
+ if path is None:
76
+ path = []
77
+
78
+ # 添加当前调用到路径
79
+ current_call = {
80
+ "level": level,
81
+ "caller_service": caller_service,
82
+ "caller_method": caller_method,
83
+ "callee_service": callee_service,
84
+ "callee_method": callee_method,
85
+ "call_type": call_type
86
+ }
87
+
88
+ path.append(current_call)
89
+
90
+ # 复制当前路径,添加到结果中
91
+ self.call_chain_results.append(path.copy())
92
+
93
+ # 递归获取下游调用
94
+ downstream_calls = self.get_downstream_calls(callee_service, callee_method)
95
+ for downstream_call in downstream_calls:
96
+ self._build_call_path(downstream_call, level + 1, path.copy())
97
+
98
+ def get_full_call_chain(self):
99
+ """
100
+ 获取完整的API调用链
101
+ :return: 字典,包含原始API信息和完整调用链
102
+ """
103
+ # 先清空之前的结果
104
+ self.visited_paths = set()
105
+ self.call_chain_results = []
106
+
107
+ # 获取起始API的下游调用
108
+ downstream_calls = self.get_downstream_calls(self.caller_service, self.caller_method)
109
+
110
+ if not downstream_calls:
111
+ logger.info(f"未找到API {self.caller_service}.{self.caller_method} 的下游调用")
112
+ return {
113
+ "api_path": self.api_path,
114
+ "service": self.caller_service,
115
+ "method": self.caller_method,
116
+ "downstream_calls_count": 0,
117
+ "downstream_calls": [],
118
+ "call_tree": {},
119
+ "statistics": {
120
+ "total_calls": 0,
121
+ "max_depth": 0,
122
+ "service_count": 0,
123
+ "call_type_distribution": {}
124
+ }
125
+ }
126
+
127
+ # 构建每个下游调用的完整路径
128
+ for call in downstream_calls:
129
+ self._build_call_path(call)
130
+
131
+ # 构建树形结构
132
+ call_tree = self._build_call_tree()
133
+
134
+ # 计算统计信息
135
+ statistics = self._calculate_statistics()
136
+
137
+ # 格式化结果
138
+ formatted_results = []
139
+ for path in self.call_chain_results:
140
+ formatted_path = {
141
+ "path_length": len(path),
142
+ "calls": []
143
+ }
144
+ for call in path:
145
+ formatted_path["calls"].append({
146
+ "level": call["level"],
147
+ "caller": f"{call['caller_service']}.{call['caller_method']}",
148
+ "callee": f"{call['callee_service']}.{call['callee_method']}",
149
+ "call_type": call["call_type"],
150
+ "detail": f"{call['caller_service']}.{call['caller_method']} -> {call['callee_service']}.{call['callee_method']} ({call['call_type']})"
151
+ })
152
+ formatted_results.append(formatted_path)
153
+
154
+ return {
155
+ "api_path": self.api_path,
156
+ "service": self.caller_service,
157
+ "method": self.caller_method,
158
+ "downstream_calls_count": len(self.call_chain_results),
159
+ "downstream_calls": formatted_results,
160
+ "call_tree": call_tree,
161
+ "statistics": statistics
162
+ }
163
+
164
+ def _build_call_tree(self):
165
+ """
166
+ 构建调用树形结构
167
+ """
168
+ tree = {}
169
+
170
+ for path in self.call_chain_results:
171
+ current_node = tree
172
+ for call in path:
173
+ key = f"{call['callee_service']}.{call['callee_method']}"
174
+ if key not in current_node:
175
+ current_node[key] = {
176
+ "service": call['callee_service'],
177
+ "method": call['callee_method'],
178
+ "call_type": call['call_type'],
179
+ "caller": f"{call['caller_service']}.{call['caller_method']}",
180
+ "children": {}
181
+ }
182
+ current_node = current_node[key]["children"]
183
+
184
+ return tree
185
+
186
+ def _calculate_statistics(self):
187
+ """
188
+ 计算调用链的统计信息
189
+ """
190
+ # 统计各种信息
191
+ service_set = set()
192
+ call_type_count = {}
193
+ max_depth = 0
194
+
195
+ for path in self.call_chain_results:
196
+ # 更新最大深度
197
+ if len(path) > max_depth:
198
+ max_depth = len(path)
199
+
200
+ # 收集服务和调用类型
201
+ for call in path:
202
+ service_set.add(call['callee_service'])
203
+ call_type = call['call_type']
204
+ call_type_count[call_type] = call_type_count.get(call_type, 0) + 1
205
+
206
+ # 统计每个服务被调用的次数
207
+ service_call_count = {}
208
+ for path in self.call_chain_results:
209
+ for call in path:
210
+ service_key = f"{call['callee_service']}.{call['callee_method']}"
211
+ service_call_count[service_key] = service_call_count.get(service_key, 0) + 1
212
+
213
+ # 找出被调用最多的服务
214
+ top_called_services = sorted(service_call_count.items(), key=lambda x: x[1], reverse=True)[:5]
215
+
216
+ return {
217
+ "total_calls": len(self.call_chain_results),
218
+ "max_depth": max_depth,
219
+ "service_count": len(service_set),
220
+ "call_type_distribution": call_type_count,
221
+ "top_called_services": top_called_services
222
+ }
223
+
224
+ def print_call_chain(self):
225
+ """
226
+ 以可读性强的格式打印完整的调用链
227
+ """
228
+ result = self.get_full_call_chain()
229
+
230
+ # 打印基本信息
231
+ print(f"\n{'=' * 100}")
232
+ print(f"📍 API调用链分析报告")
233
+ print(f"{'=' * 100}")
234
+ print(f"🔗 API路径: {result['api_path']}")
235
+ print(f"🏢 服务名: {result['service']}")
236
+ print(f"📋 方法名: {result['method']}")
237
+ print(f"\n{'=' * 100}")
238
+
239
+ # 打印统计信息
240
+ stats = result['statistics']
241
+ print(f"📊 统计信息:")
242
+ print(f" • 总调用链数: {stats['total_calls']}")
243
+ print(f" • 最大调用深度: {stats['max_depth']}")
244
+ print(f" • 涉及服务数量: {stats['service_count']}")
245
+ print(f" • 调用类型分布: {stats['call_type_distribution']}")
246
+
247
+ if stats.get('top_called_services'):
248
+ print(f"\n • 🔥 高频调用服务 TOP5:")
249
+ for service, count in stats['top_called_services']:
250
+ print(f" - {service} (被调用 {count} 次)")
251
+
252
+ print(f"\n{'=' * 100}")
253
+
254
+ if result.get('downstream_calls_count', 0) == 0:
255
+ print("❌ 没有找到下游调用")
256
+ print(f"{'=' * 100}\n")
257
+ return result
258
+
259
+ # 打印树形结构
260
+ print("🌳 调用树形结构:")
261
+ print(f"{'-' * 100}")
262
+ self._print_tree(result['call_tree'], indent=0)
263
+
264
+ return result
265
+
266
+ def _print_tree(self, tree, indent=0, prefix=""):
267
+ """
268
+ 递归打印树形结构
269
+ """
270
+ items = list(tree.items())
271
+ for i, (key, node) in enumerate(items):
272
+ is_last = i == len(items) - 1
273
+
274
+ # 打印当前节点
275
+ connector = "└── " if is_last else "├── "
276
+ type_symbol = {"HTTP": "🌐", "RPC": "⚡", "LOCAL": "🏠"}.get(node['call_type'], "📡")
277
+ print(f"{prefix}{connector}{type_symbol} {key}")
278
+
279
+ # 打印子节点
280
+ if node['children']:
281
+ extension = " " if is_last else "│ "
282
+ self._print_tree(node['children'], indent + 1, prefix + extension)
283
+
284
+
285
+ if __name__ == '__main__':
286
+ # 使用示例 - HTTP路径格式
287
+ api_path_ = "/weaver/api/v1/ugc/get_npc_list_by_user_id"
288
+ call_chain = GetFullApiCallChain(api_path_)
289
+ result = call_chain.print_call_chain()
290
+ print("结果:")
291
+ print(result)
@@ -0,0 +1,175 @@
1
+ """
2
+ coding:utf-8
3
+ @Software: PyCharm
4
+ @Time: 2024/6/4 下午5:48
5
+ @Author: xingyun
6
+ """
7
+
8
+ import pymysql
9
+
10
+ from minimax_qa_mcp.utils.logger import logger
11
+
12
+
13
+ class MysqlOp(object):
14
+ def __init__(self):
15
+ self.password = "ngo0nZYnPvpoke7P"
16
+ self.host = "10.11.24.40"
17
+ self.database = "qa_tools"
18
+ self.user = "qa_test"
19
+ self.port = 3306
20
+
21
+ def connect(self, sql_, data=None, op=None):
22
+ # 连接到MySQL数据库
23
+ conn = pymysql.connect(host=self.host,
24
+ user=self.user,
25
+ password=self.password,
26
+ db=self.database,
27
+ port=self.port)
28
+
29
+ # 创建Cursor对象
30
+ try:
31
+ with conn.cursor() as cursor:
32
+ if op == 'insert':
33
+ cursor.execute(sql_, data)
34
+ conn.commit()
35
+ # 插入成功后,可以获取插入数据的ID(如果表有自增主键)
36
+ last_id = cursor.lastrowid
37
+ logger.info(f"Last inserted record ID is {last_id}")
38
+ return last_id
39
+ elif op == 'select':
40
+ cursor.execute(sql_, data)
41
+ # 获取查询结果
42
+ results = cursor.fetchall()
43
+ # 打印结果
44
+ for row in results:
45
+ logger.info(row)
46
+ return results
47
+ elif op == 'delete':
48
+ cursor.execute(sql_, data)
49
+ # 提交到数据库执行
50
+ conn.commit()
51
+ logger.info("记录已成功删除。")
52
+ elif op == 'update':
53
+ cursor.execute(sql_, data)
54
+ # 提交到数据库执行
55
+ conn.commit()
56
+ logger.info("数据更新成功!")
57
+ # 获取更新的行数
58
+ affected_rows = cursor.rowcount
59
+ logger.info(f"Number of rows affected: {affected_rows}")
60
+ return affected_rows
61
+
62
+ except pymysql.MySQLError as e:
63
+ # 如果发生错误,打印错误信息
64
+ logger.info(f"Error: {e}")
65
+ finally:
66
+ # 关闭Cursor和Connection
67
+ conn.close()
68
+
69
+ def batch_insert(self, sql_, batch_data):
70
+ """
71
+ 批量插入数据到MySQL数据库
72
+ :param sql_: 带有占位符的SQL插入语句
73
+ :param batch_data: 包含多组参数的列表,每组参数对应一条记录
74
+ :return: 成功插入的记录数
75
+ """
76
+ if not batch_data:
77
+ logger.info("批量插入数据为空,跳过")
78
+ return 0
79
+
80
+ # 连接到MySQL数据库
81
+ conn = pymysql.connect(host=self.host,
82
+ user=self.user,
83
+ password=self.password,
84
+ db=self.database,
85
+ port=self.port)
86
+
87
+ success_count = 0
88
+ try:
89
+ with conn.cursor() as cursor:
90
+ # 执行批量插入
91
+ success_count = cursor.executemany(sql_, batch_data)
92
+ conn.commit()
93
+ logger.info(f"成功批量插入 {success_count} 条记录")
94
+ return success_count
95
+ except pymysql.MySQLError as e:
96
+ # 如果发生错误,回滚事务并打印错误信息
97
+ conn.rollback()
98
+ logger.info(f"批量插入错误: {e}")
99
+ return 0
100
+ finally:
101
+ # 关闭连接
102
+ conn.close()
103
+
104
+ def batch_update(self, sql_, batch_data):
105
+ """
106
+ 批量更新MySQL数据库中的记录
107
+ :param sql_: 带有占位符的SQL更新语句
108
+ :param batch_data: 包含多组参数的列表,每组参数对应一条记录
109
+ :return: 成功更新的记录数
110
+ """
111
+ if not batch_data:
112
+ logger.info("批量更新数据为空,跳过")
113
+ return 0
114
+
115
+ # 连接到MySQL数据库
116
+ conn = pymysql.connect(host=self.host,
117
+ user=self.user,
118
+ password=self.password,
119
+ db=self.database,
120
+ port=self.port)
121
+
122
+ success_count = 0
123
+ try:
124
+ with conn.cursor() as cursor:
125
+ # 执行批量更新
126
+ success_count = cursor.executemany(sql_, batch_data)
127
+ conn.commit()
128
+ logger.info(f"成功批量更新 {success_count} 条记录")
129
+ return success_count
130
+ except pymysql.MySQLError as e:
131
+ # 如果发生错误,回滚事务并打印错误信息
132
+ conn.rollback()
133
+ logger.info(f"批量更新错误: {e}")
134
+ return 0
135
+ finally:
136
+ # 关闭连接
137
+ conn.close()
138
+
139
+
140
+ if __name__ == '__main__':
141
+ # group_id = '112233445566'
142
+ # bank_account_no = 'test_1234'
143
+ # card_num = 'test_card_num'
144
+ # redis_key = 'cred_group_id_data'
145
+ # ping_an_resp = 'xxx'
146
+ # time_stamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
147
+ # mysql_op = MysqlOp('qa_db')
148
+ # # sql_ = 'insert into pingan_un_bank_info (group_id, bank_account_no, card_num, redis_key, pingan_url_resp, creat_time, delete_time) values (%s, %s, %s, %s, %s, %s, %s)'
149
+ # # mysql_op.connect(sql_=sql_, data=(group_id, bank_account_no, card_num, redis_key, ping_an_resp, time_stamp, time_stamp), op='insert')
150
+ # update_sql = 'update pingan_un_bank_info set pingan_url_resp = %s where group_id = %s'
151
+ # mysql_op.connect(sql_=update_sql, data=('test_resp sxxxxxxxxxxxxxx', '112233445566'), op='update')
152
+
153
+ # operator_ = 'xingyun1'
154
+ # psm_ = 'open_platform'
155
+ # task_name_ = '开放平台线上环境巡检'
156
+ # job_id = '20240612124204'
157
+ # report_url_ = ''
158
+ # report_tos_key_ = 'qa-tool-1315599187/swingReport/20240604/swing_report_20240604_123456.zip'
159
+ # status_ = True
160
+ # create_time_ = str(datetime.now())
161
+ # env_ = 'prod'
162
+ # sql = 'insert into swing_report (operator, psm, task_name, task_id, report_tos_key, status, create_time, env, job_id) values (%s, %s, %s, %s, %s, %s, %s, %s, %s)'
163
+ # MysqlOp().connect(sql, data=(operator_, psm_, task_name_, task_id_, report_tos_key_, status_, create_time_, env_, job_id), op='insert')
164
+ # sql = 'select * from swing_report limit 10'
165
+ # sql = 'select * from user_group limit 10'
166
+ # # # sql = 'delete from swing_report where operator = %s'
167
+ # # mys = MysqlOp('kaiping_usercore_online_db')
168
+ # mys.connect(sql_=sql, data=None, op='select')
169
+ # sql = 'update swing_report set status = %s where id = %s'
170
+ # mys.connect(sql_=sql, data=('2', 1), op='update')
171
+ sql = "select * from qa_tools.api_meta where psm_name = %s"
172
+ mysql_op = MysqlOp()
173
+ result = mysql_op.connect(sql, data=('weaver.conversation.biz',), op='select')
174
+ print(result)
175
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm_qa_mcp
3
- Version: 1.0.0
3
+ Version: 2.0.0
4
4
  Summary: QA agent service 集合
5
5
  Author-email: xingyun <xingyun@minimaxi.com>
6
6
  License: MIT
@@ -1,15 +1,15 @@
1
1
  minimax_qa_mcp/__init__.py,sha256=7r3jCBYTrmA8VWKtzFA-WSHnlRND2xg9oaZDFV3ozWA,188
2
- minimax_qa_mcp/server.py,sha256=OS-AT-uPSWWW5-HQPcpN24w9IxiSVMQOQ_7KfNbabik,8197
2
+ minimax_qa_mcp/server.py,sha256=Vo6Cu6VYvdaOTGyDs7aXeof3VTk5Yw12-x2Lp4pCUhs,8793
3
3
  minimax_qa_mcp/conf/__init__.py,sha256=s_q9K05OfxIzPXLshF3qPedjADeGzjlfU4w_6PiR62g,85
4
4
  minimax_qa_mcp/conf/conf.ini,sha256=ny4CtXIib0ggTxI7wmT4v3dZcdNadN7EcUFcyeREaqo,2393
5
5
  minimax_qa_mcp/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- minimax_qa_mcp/src/demo_langchain/__init__.py,sha256=PZDCBXwlgCJ-UMfOikaTGBrLcOtpJVbuPBzM6RdiLlg,80
7
- minimax_qa_mcp/src/demo_langchain/langchain_demo.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
8
6
  minimax_qa_mcp/src/gateway_case/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
7
  minimax_qa_mcp/src/gateway_case/get_case.py,sha256=djn77_zn_252Mhmk_qn_9k_uz4NAjadq2bEnKyPi7iw,27116
10
8
  minimax_qa_mcp/src/generator_case/__init__.py,sha256=Sy4ncJFUvzzFAlwlJAC7cQ2YdD4JFXpmovG3jVVboHc,79
11
9
  minimax_qa_mcp/src/generator_case/generator_case.py,sha256=qpI_1hWbR2jEQGQikhJnjjpLCDwSwvbjnA5ujDgiAjY,50090
12
10
  minimax_qa_mcp/src/generator_case/generator_case_langchain.py,sha256=qD5Ibxnvj5A22zxnuuhxcdDlILZQkburDILJezlQ4VI,43262
11
+ minimax_qa_mcp/src/get_full_api_call_chain/__init__.py,sha256=DFpdx_aSmQ31Ud038PN9jhvP-fHdb4c9Ie3dAmIRAus,79
12
+ minimax_qa_mcp/src/get_full_api_call_chain/get_full_api_call_chain.py,sha256=Zj56x_c-0-lJ5XOHQ2QioIW2q_hVPEowVlI6jyTNzqI,10154
13
13
  minimax_qa_mcp/src/get_weaviate_info/__init__.py,sha256=sMKXpobyDsZBnRFR7ozqPfpJEN1x3cIBM7mTTPrv1PE,80
14
14
  minimax_qa_mcp/src/get_weaviate_info/get_weaviate_info.py,sha256=BLnRN96S4EOrOc3Cqf-QSSzVDMYieB7hA7NCwdsLadI,10415
15
15
  minimax_qa_mcp/src/grafana/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -20,9 +20,10 @@ minimax_qa_mcp/src/xmind2markdown/__init__.py,sha256=IqnCkza9xw5r-0mEetNQoQrkoX-
20
20
  minimax_qa_mcp/src/xmind2markdown/xmind_to_markdown.py,sha256=86WZ4aTf1Y4jDLsoBaJZySOeU0G__j_8ZBAtQqccdV4,41903
21
21
  minimax_qa_mcp/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  minimax_qa_mcp/utils/logger.py,sha256=R1SyLTra9ngjSu4vKJ21krgl83Or33Q0dRz6-K_OYS8,1089
23
+ minimax_qa_mcp/utils/mysql_op.py,sha256=aF2li7YKMGreq0LFg0WwIWO5rGDpx3Qg4l0--HNsyK0,7085
23
24
  minimax_qa_mcp/utils/utils.py,sha256=Xb9d6lz4p3wVDbLKrctfG3v5_Lx1ge6vFMmtAqZ9qF4,8703
24
- mm_qa_mcp-1.0.0.dist-info/METADATA,sha256=hQtF4k6AqcQPBKwsQ7LbE20Y_p8_UUQJinkXegsdNQA,6281
25
- mm_qa_mcp-1.0.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
26
- mm_qa_mcp-1.0.0.dist-info/entry_points.txt,sha256=iP2Pl72UfrJCDakHv_Zxg6ci6gtvZipc8cN1SvqueJk,63
27
- mm_qa_mcp-1.0.0.dist-info/top_level.txt,sha256=cXfV8AjI2zW5yK2aw4Z2TMV9oRPx6eU04K9ZxwqAtxw,15
28
- mm_qa_mcp-1.0.0.dist-info/RECORD,,
25
+ mm_qa_mcp-2.0.0.dist-info/METADATA,sha256=6Fq4T0KPlQlW4heGjHrr6XDhR4LGesP4vphRMMORx0I,6281
26
+ mm_qa_mcp-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ mm_qa_mcp-2.0.0.dist-info/entry_points.txt,sha256=iP2Pl72UfrJCDakHv_Zxg6ci6gtvZipc8cN1SvqueJk,63
28
+ mm_qa_mcp-2.0.0.dist-info/top_level.txt,sha256=cXfV8AjI2zW5yK2aw4Z2TMV9oRPx6eU04K9ZxwqAtxw,15
29
+ mm_qa_mcp-2.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5