Add customization of prompts for MCP tools

This commit is contained in:
dimitrievgs 2026-06-14 01:33:20 +03:00
parent 82891822a5
commit c4995d5088
3 changed files with 79 additions and 3 deletions

View File

@ -11,6 +11,7 @@ from flask_socketio import SocketIO
from workflows import graph_history_manager, run_agent_streaming from workflows import graph_history_manager, run_agent_streaming
from llm_client import DEFAULT_TEMPERATURE, MODELS, get_llm # Добавляем импорт списка моделей from llm_client import DEFAULT_TEMPERATURE, MODELS, get_llm # Добавляем импорт списка моделей
import base64 import base64
from mcp_tools import get_raw_mcp_tools_list
api = Flask(__name__) api = Flask(__name__)
CORS( CORS(
@ -414,6 +415,20 @@ def regenerate_message():
return jsonify({"error": str(e)}, 500) return jsonify({"error": str(e)}, 500)
@api.route('/api/mcp/fetch', methods=['POST'])
def fetch_mcp_tools_route():
"""API endpoint для получения списка инструментов MCP сервера (без создания LangChain тулов)"""
server_config = request.get_json()
if not server_config:
return jsonify({"error": "Пустой конфиг сервера"}), 400
try:
tools_list = get_raw_mcp_tools_list(server_config)
return jsonify(tools_list)
except Exception as e:
return jsonify({"error": str(e)}), 500
from voice_service import VoiceService, VOICE_COMMANDS_RESPONSE_TO_STORE from voice_service import VoiceService, VOICE_COMMANDS_RESPONSE_TO_STORE
# 1. Создаем экземпляр (обязательно укажите путь к вашей модели Vosk) # 1. Создаем экземпляр (обязательно укажите путь к вашей модели Vosk)

View File

@ -115,11 +115,59 @@ def fetch_mcp_tools(server_config, debug_callback=None):
try: try:
raw_tools, full_env, args = asyncio.run(_fetch()) raw_tools, full_env, args = asyncio.run(_fetch())
wrapped_tools = [] wrapped_tools = []
# Получаем кастомные описания из конфига
fetched_tools_ui = server_config.get("fetchedTools", [])
custom_descriptions = {t.get("name"): t.get("customDescription") for t in fetched_tools_ui}
for t in raw_tools: for t in raw_tools:
wrapped_tools.append(create_mcp_tool(server_config, t.name, t.description, t.inputSchema, full_env, args, debug_callback)) # Если есть кастомное описание и оно не пустое - используем его
c_desc = custom_descriptions.get(t.name)
final_description = c_desc if c_desc and c_desc.strip() else t.description
wrapped_tools.append(create_mcp_tool(server_config, t.name, final_description, t.inputSchema, full_env, args, debug_callback))
_MCP_CACHED_TOOLS[config_hash] = wrapped_tools _MCP_CACHED_TOOLS[config_hash] = wrapped_tools
print(f"🔌 Успешно загружено {len(wrapped_tools)} инструментов от MCP-сервера '{server_config.get('name')}'") print(f"🔌 Успешно загружено {len(wrapped_tools)} инструментов от MCP-сервера '{server_config.get('name')}'")
return wrapped_tools return wrapped_tools
except Exception as e: except Exception as e:
print(f"❌ Ошибка инициализации MCP сервера {server_config.get('name')}: {e}") print(f"❌ Ошибка инициализации MCP сервера {server_config.get('name')}: {e}")
return [] return []
def get_raw_mcp_tools_list(server_config):
"""Метод для UI: просто возвращает список доступных инструментов в JSON-friendly формате"""
if not MCP_AVAILABLE:
return []
import asyncio
import shlex
import os
async def _fetch_raw():
command = server_config.get("command", "")
args_str = server_config.get("args", "")
args = shlex.split(args_str) if args_str else []
env_dict = {}
env_str = server_config.get("envString", "")
if env_str:
for pair in env_str.split(','):
if '=' in pair:
k, v = pair.split('=', 1)
env_dict[k.strip()] = v.strip()
full_env = {**os.environ.copy(), **env_dict}
server_params = StdioServerParameters(command=command, args=args, env=full_env)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools_resp = await session.list_tools()
return tools_resp.tools
try:
raw_tools = asyncio.run(_fetch_raw())
return [{"name": t.name, "description": t.description} for t in raw_tools]
except Exception as e:
print(f"Ошибка получения списка тулов: {e}")
return []

View File

@ -40,8 +40,21 @@ def run_agent_streaming(graph_id: str,
# 2. Формируем контекст LangChain с учетом файлов и изображений (вложений) # 2. Формируем контекст LangChain с учетом файлов и изображений (вложений)
messages_for_llm = [] messages_for_llm = []
if system_prompt:
messages_for_llm.append(SystemMessage(content=system_prompt)) # Собираем над-инструкции для MCP серверов
mcp_instructions = []
if obsidian_settings and obsidian_settings.get("mcpServers"):
for server in obsidian_settings.get("mcpServers", []):
s_instr = server.get("serverInstruction")
if s_instr and s_instr.strip():
mcp_instructions.append(f"Инструкции для использования инструментов сервера '{server.get('name')}':\n{s_instr.strip()}")
final_system_prompt = system_prompt or ""
if mcp_instructions:
final_system_prompt += "\n\n" + "\n\n".join(mcp_instructions)
if final_system_prompt:
messages_for_llm.append(SystemMessage(content=final_system_prompt.strip()))
# Обрабатываем вложения # Обрабатываем вложения
for i, msg in enumerate(messages): for i, msg in enumerate(messages):