1
1
import json
2
2
import asyncio
3
3
from concurrent .futures import Future
4
- from core .utils .util import get_vision_url
4
+ from core .utils .util import get_vision_url , sanitize_tool_name
5
5
from core .utils .auth import AuthToken
6
6
7
7
TAG = __name__
@@ -11,7 +11,8 @@ class MCPClient:
11
11
"""MCPClient,用于管理MCP状态和工具"""
12
12
13
13
def __init__ (self ):
14
- self .tools = {} # Dictionary for O(1) lookup
14
+ self .tools = {} # sanitized_name -> tool_data
15
+ self .name_mapping = {}
15
16
self .ready = False
16
17
self .call_results = {} # To store Futures for tool call responses
17
18
self .next_id = 1
@@ -30,7 +31,7 @@ def get_available_tools(self) -> list:
30
31
result = []
31
32
for tool_name , tool_data in self .tools .items ():
32
33
function_def = {
33
- "name" : tool_data [ "name" ] ,
34
+ "name" : tool_name ,
34
35
"description" : tool_data ["description" ],
35
36
"parameters" : {
36
37
"type" : tool_data ["inputSchema" ].get ("type" , "object" ),
@@ -53,7 +54,9 @@ async def set_ready(self, status: bool):
53
54
54
55
async def add_tool (self , tool_data : dict ):
55
56
async with self .lock :
56
- self .tools [tool_data ["name" ]] = tool_data
57
+ sanitized_name = sanitize_tool_name (tool_data ["name" ])
58
+ self .tools [sanitized_name ] = tool_data
59
+ self .name_mapping [sanitized_name ] = tool_data ["name" ]
57
60
self ._cached_available_tools = (
58
61
None # Invalidate the cache when a tool is added
59
62
)
@@ -133,9 +136,6 @@ async def handle_mcp_message(conn, mcp_client: MCPClient, payload: dict):
133
136
conn .logger .bind (tag = TAG ).info (
134
137
f"客户端MCP服务器信息: name={ name } , version={ version } "
135
138
)
136
- await send_mcp_tools_list_request (
137
- conn
138
- ) # After initialization, request tool list
139
139
return
140
140
141
141
elif msg_id == 2 : # mcpToolsListID
@@ -174,6 +174,20 @@ async def handle_mcp_message(conn, mcp_client: MCPClient, payload: dict):
174
174
await mcp_client .add_tool (new_tool )
175
175
conn .logger .bind (tag = TAG ).debug (f"客户端工具 #{ i + 1 } : { name } " )
176
176
177
+ # 替换所有工具描述中的工具名称
178
+ for tool_data in mcp_client .tools .values ():
179
+ if "description" in tool_data :
180
+ description = tool_data ["description" ]
181
+ # 遍历所有工具名称进行替换
182
+ for (
183
+ sanitized_name ,
184
+ original_name ,
185
+ ) in mcp_client .name_mapping .items ():
186
+ description = description .replace (
187
+ original_name , sanitized_name
188
+ )
189
+ tool_data ["description" ] = description
190
+
177
191
next_cursor = result .get ("nextCursor" , "" )
178
192
if next_cursor :
179
193
conn .logger .bind (tag = TAG ).info (
@@ -219,8 +233,6 @@ async def send_mcp_initialize_message(conn):
219
233
"token" : token ,
220
234
}
221
235
222
- conn .logger .bind (tag = TAG ).info (f"视觉服务信息: { vision } " )
223
-
224
236
payload = {
225
237
"jsonrpc" : "2.0" ,
226
238
"id" : 1 , # mcpInitializeID
@@ -333,23 +345,24 @@ async def call_mcp_tool(
333
345
raise ValueError (f"参数处理失败: { str (e )} " )
334
346
raise e
335
347
348
+ actual_name = mcp_client .name_mapping .get (tool_name , tool_name )
336
349
payload = {
337
350
"jsonrpc" : "2.0" ,
338
351
"id" : tool_call_id ,
339
352
"method" : "tools/call" ,
340
- "params" : {"name" : tool_name , "arguments" : arguments },
353
+ "params" : {"name" : actual_name , "arguments" : arguments },
341
354
}
342
355
343
356
conn .logger .bind (tag = TAG ).info (
344
- f"发送客户端mcp工具调用请求: { tool_name } ,参数: { args } "
357
+ f"发送客户端mcp工具调用请求: { actual_name } ,参数: { args } "
345
358
)
346
359
await send_mcp_message (conn , payload )
347
360
348
361
try :
349
362
# Wait for response or timeout
350
363
raw_result = await asyncio .wait_for (result_future , timeout = timeout )
351
364
conn .logger .bind (tag = TAG ).info (
352
- f"客户端mcp工具调用 { tool_name } 成功,原始结果: { raw_result } "
365
+ f"客户端mcp工具调用 { actual_name } 成功,原始结果: { raw_result } "
353
366
)
354
367
355
368
if isinstance (raw_result , dict ):
0 commit comments