diff --git a/CHANGELOG.md b/CHANGELOG.md index d758fea..768bd7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - 新特性:更新协议内容,支持 streamable http 协议,未来将逐步取代 SSE 的连接方式 - 对于 uv 创建的 py 项目进行特殊支持:自动初始化项目,并将 mcp 定向到 .venv/bin/mcp 中,不再需要用户全局安装 mcp - 对于 npm 创建的 js/ts 项目进行特殊支持:自动初始化项目 +- 去除了 websearch 的设置,增加了 parallel_tool_calls 的设置,parallel_tool_calls 默认为 true,代表 允许模型在单轮回复中调用多个工具 +- 重构了 openmcp 连接模块的基础设施,基于新的技术设施实现了更加详细的连接模块的日志系统 ## [main] 0.0.9 - 修复 0.0.8 引入的bug:system prompt 返回的是索引而非真实内容 diff --git a/README.md b/README.md index dc80bf8..4169476 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ | `ext` | 支持基本的 MCP 项目管理 | `迭代版本` | 100% | `P0` | | `service` | 支持自定义支持 openai 接口协议的大模型接入 | `完整版本` | 100% | `Done` | | `service` | 支持自定义接口协议的大模型接入 | `MVP` | 0% | `P1` | -| `all` | 支持同时调试多个 MCP Server | `MVP` | 80% | `P0` | +| `all` | 支持同时调试多个 MCP Server | `MVP` | 100% | `P0` | | `all` | 支持通过大模型进行在线验证 | `迭代版本` | 100% | `Done` | | `all` | 支持对用户对应服务器的调试工作内容进行保存 | `迭代版本` | 100% | `Done` | | `render` | 高危操作权限确认 | `MVP` | 0% | `P1` | diff --git a/renderer/public/iconfont.css b/renderer/public/iconfont.css index feacc0c..2f32010 100644 --- a/renderer/public/iconfont.css +++ b/renderer/public/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 4870215 */ - src: url('iconfont.woff2?t=1746703816245') format('woff2'), - url('iconfont.woff?t=1746703816245') format('woff'), - url('iconfont.ttf?t=1746703816245') format('truetype'); + src: url('iconfont.woff2?t=1747820198035') format('woff2'), + url('iconfont.woff?t=1747820198035') format('woff'), + url('iconfont.ttf?t=1747820198035') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-parallel:before { + content: "\e61d"; +} + .icon-waiting:before { content: "\e6d0"; } diff --git a/renderer/public/iconfont.woff2 b/renderer/public/iconfont.woff2 index 45332ae..6e2c510 100644 Binary files a/renderer/public/iconfont.woff2 and b/renderer/public/iconfont.woff2 differ diff --git a/renderer/src/components/main-panel/chat/chat-box/chat.ts b/renderer/src/components/main-panel/chat/chat-box/chat.ts index 0258567..5af36dd 100644 --- a/renderer/src/components/main-panel/chat/chat-box/chat.ts +++ b/renderer/src/components/main-panel/chat/chat-box/chat.ts @@ -47,11 +47,11 @@ export interface TextMessage { export type ChatMessage = ToolMessage | TextMessage; // 新增状态和工具数据 -interface EnableToolItem { - name: string; - description: string; - enabled: boolean; - inputSchema?: any; +export interface EnableToolItem { + name: string; + description: string; + enabled: boolean; + inputSchema: any; } export interface ChatSetting { @@ -61,10 +61,11 @@ export interface ChatSetting { temperature: number enableWebSearch: boolean contextLength: number + parallelToolCalls: boolean } export interface ChatStorage { - messages: ChatMessage[] + messages: ChatMessage[] settings: ChatSetting } @@ -95,8 +96,6 @@ interface TextItem { export type RichTextItem = PromptTextItem | ResourceTextItem | TextItem; -export const allTools = ref([]); - export interface ICommonRenderMessage { role: 'user' | 'assistant/content'; content: string; @@ -110,41 +109,27 @@ export interface IToolRenderMessage { toolResults: ToolCallContent[][]; tool_calls: ToolCall[]; showJson?: Ref; - extraInfo: IExtraInfo; + extraInfo: IExtraInfo; } export type IRenderMessage = ICommonRenderMessage | IToolRenderMessage; export function getToolSchema(enableTools: EnableToolItem[]) { const toolsSchema = []; - for (let i = 0; i < enableTools.length; i++) { + for (let i = 0; i < enableTools.length; i++) { const enableTool = enableTools[i]; if (enableTool.enabled) { - - if (enableTool.inputSchema) { - toolsSchema.push({ - type: 'function', - function: { - name: enableTool.name, - description: enableTool.description || "", - parameters: enableTool.inputSchema - } - }); - } else { - const tool = allTools.value[i]; - - toolsSchema.push({ - type: 'function', - function: { - name: tool.name, - description: tool.description || "", - parameters: tool.inputSchema - } - }); - } - } - } + toolsSchema.push({ + type: 'function', + function: { + name: enableTool.name, + description: enableTool.description || "", + parameters: enableTool.inputSchema + } + }); + } + } return toolsSchema; } diff --git a/renderer/src/components/main-panel/chat/chat-box/options/parallel-tool-calls.vue b/renderer/src/components/main-panel/chat/chat-box/options/parallel-tool-calls.vue new file mode 100644 index 0000000..a9f58c5 --- /dev/null +++ b/renderer/src/components/main-panel/chat/chat-box/options/parallel-tool-calls.vue @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/renderer/src/components/main-panel/chat/chat-box/options/setting.vue b/renderer/src/components/main-panel/chat/chat-box/options/setting.vue index acf72f6..acf23e1 100644 --- a/renderer/src/components/main-panel/chat/chat-box/options/setting.vue +++ b/renderer/src/components/main-panel/chat/chat-box/options/setting.vue @@ -5,7 +5,7 @@ - + @@ -22,7 +22,7 @@ import SystemPrompt from './system-prompt.vue'; import ToolUse from './tool-use.vue'; import Prompt from './prompt.vue'; import Resource from './resource.vue'; -import Websearch from './websearch.vue'; +import ParallelToolCalls from './parallel-tool-calls.vue'; import Temperature from './temperature.vue'; import ContextLength from './context-length.vue'; @@ -57,9 +57,10 @@ if (!tabStorage.settings) { modelIndex: llmManager.currentModelIndex, enableTools: [], enableWebSearch: false, - temperature: 0.7, + temperature: 0.6, contextLength: 20, - systemPrompt: '' + systemPrompt: '', + parallelToolCalls: true } as ChatSetting; } diff --git a/renderer/src/components/main-panel/chat/chat-box/options/tool-use.vue b/renderer/src/components/main-panel/chat/chat-box/options/tool-use.vue index e9ace2a..d7b92ec 100644 --- a/renderer/src/components/main-panel/chat/chat-box/options/tool-use.vue +++ b/renderer/src/components/main-panel/chat/chat-box/options/tool-use.vue @@ -37,9 +37,9 @@ diff --git a/renderer/src/components/main-panel/chat/core/handle-tool-calls.ts b/renderer/src/components/main-panel/chat/core/handle-tool-calls.ts index 41b3379..05d2b8f 100644 --- a/renderer/src/components/main-panel/chat/core/handle-tool-calls.ts +++ b/renderer/src/components/main-panel/chat/core/handle-tool-calls.ts @@ -1,6 +1,6 @@ import type { ToolCallContent, ToolCallResponse } from "@/hook/type"; -import { callTool } from "../../tool/tools"; import { MessageState, type ToolCall } from "../chat-box/chat"; +import { mcpClientAdapter } from "@/views/connect/core"; export interface ToolCallResult { state: MessageState; @@ -25,7 +25,7 @@ export async function handleToolCalls(toolCall: ToolCall): Promise { - for (const client of mcpClientAdapter.clients) { - await client.getPromptTemplates(); - } - if (tabStorage.currentPromptName === undefined) { const masterNode = mcpClientAdapter.masterNode; const prompt = masterNode.promptTemplates?.values().next(); diff --git a/renderer/src/components/main-panel/resource/resource-list-templates.vue b/renderer/src/components/main-panel/resource/resource-list-templates.vue index ba0e76e..e4a428d 100644 --- a/renderer/src/components/main-panel/resource/resource-list-templates.vue +++ b/renderer/src/components/main-panel/resource/resource-list-templates.vue @@ -89,10 +89,6 @@ function handleClick(template: ResourceTemplate) { } onMounted(async () => { - for (const client of mcpClientAdapter.clients) { - await client.getResourceTemplates({ cache: false }); - } - if (tabStorage.currentResourceName === undefined && tabStorage.currentType === 'template') { const masterNode = mcpClientAdapter.masterNode; const resourceTemplate = masterNode?.resourceTemplates?.values().next(); diff --git a/renderer/src/components/main-panel/resource/resource-list.vue b/renderer/src/components/main-panel/resource/resource-list.vue index 8b5122c..6e46bc3 100644 --- a/renderer/src/components/main-panel/resource/resource-list.vue +++ b/renderer/src/components/main-panel/resource/resource-list.vue @@ -91,10 +91,6 @@ async function handleClick(resource: Resources) { } onMounted(async () => { - for (const client of mcpClientAdapter.clients) { - await client.getResources(); - } - if (tabStorage.currentResourceName === undefined && tabStorage.currentType === 'resource') { const masterNode = mcpClientAdapter.masterNode; const resource = masterNode.resources?.values().next(); diff --git a/renderer/src/components/main-panel/tool/tool-list.vue b/renderer/src/components/main-panel/tool/tool-list.vue index d59cd02..79ee547 100644 --- a/renderer/src/components/main-panel/tool/tool-list.vue +++ b/renderer/src/components/main-panel/tool/tool-list.vue @@ -65,10 +65,6 @@ function handleClick(tool: { name: string }) { } onMounted(async () => { - for (const client of mcpClientAdapter.clients) { - await client.getTools(); - } - if (tabStorage.currentToolName === undefined) { const masterNode = mcpClientAdapter.masterNode; const tool = masterNode.tools?.values().next(); diff --git a/renderer/src/components/main-panel/tool/tools.ts b/renderer/src/components/main-panel/tool/tools.ts index de46429..030200b 100644 --- a/renderer/src/components/main-panel/tool/tools.ts +++ b/renderer/src/components/main-panel/tool/tools.ts @@ -1,7 +1,4 @@ -import { useMessageBridge } from '@/api/message-bridge'; -import { mcpSetting } from '@/hook/mcp'; -import type { ToolsListResponse, ToolCallResponse, CasualRestAPI } from '@/hook/type'; -import { mcpClientAdapter } from '@/views/connect/core'; +import type { ToolCallResponse } from '@/hook/type'; export interface ToolStorage { activeNames: any[]; @@ -9,25 +6,3 @@ export interface ToolStorage { lastToolCallResponse?: ToolCallResponse | string; formData: Record; } - -/** - * @description 根据工具名字和参数调取工具 - * @param toolName - * @param toolArgs - * @returns - */ -export async function callTool(toolName: string, toolArgs: Record) { - - mcpClientAdapter - - const bridge = useMessageBridge(); - const { msg } = await bridge.commandRequest('tools/call', { - toolName, - toolArgs: JSON.parse(JSON.stringify(toolArgs)), - callToolOption: { - timeout: mcpSetting.timeout * 1000 - } - }); - - return msg; -} \ No newline at end of file diff --git a/renderer/src/i18n/ar.json b/renderer/src/i18n/ar.json index 58772fc..97ce616 100644 --- a/renderer/src/i18n/ar.json +++ b/renderer/src/i18n/ar.json @@ -155,5 +155,6 @@ "return": "عودة", "error": "خطأ", "feedback": "تعليقات", - "waiting-mcp-server": "في انتظار استجابة خادم MCP" + "waiting-mcp-server": "في انتظار استجابة خادم MCP", + "parallel-tool-calls": "السماح للنموذج باستدعاء أدوات متعددة في رد واحد" } \ No newline at end of file diff --git a/renderer/src/i18n/de.json b/renderer/src/i18n/de.json index 4c569c2..be8f275 100644 --- a/renderer/src/i18n/de.json +++ b/renderer/src/i18n/de.json @@ -155,5 +155,6 @@ "return": "Zurück", "error": "Fehler", "feedback": "Feedback", - "waiting-mcp-server": "Warten auf Antwort vom MCP-Server" + "waiting-mcp-server": "Warten auf Antwort vom MCP-Server", + "parallel-tool-calls": "Erlauben Sie dem Modell, mehrere Tools in einer einzigen Antwort aufzurufen" } \ No newline at end of file diff --git a/renderer/src/i18n/en.json b/renderer/src/i18n/en.json index 5c9ab7c..a1e41e5 100644 --- a/renderer/src/i18n/en.json +++ b/renderer/src/i18n/en.json @@ -155,5 +155,6 @@ "return": "Back", "error": "Error", "feedback": "Feedback", - "waiting-mcp-server": "Waiting for MCP server response" + "waiting-mcp-server": "Waiting for MCP server response", + "parallel-tool-calls": "Allow the model to call multiple tools in a single reply" } \ No newline at end of file diff --git a/renderer/src/i18n/fr.json b/renderer/src/i18n/fr.json index e73832a..b553741 100644 --- a/renderer/src/i18n/fr.json +++ b/renderer/src/i18n/fr.json @@ -155,5 +155,6 @@ "return": "Retour", "error": "Erreur", "feedback": "Retour", - "waiting-mcp-server": "En attente de la réponse du serveur MCP" + "waiting-mcp-server": "En attente de la réponse du serveur MCP", + "parallel-tool-calls": "Permettre au modèle d'appeler plusieurs outils en une seule réponse" } \ No newline at end of file diff --git a/renderer/src/i18n/ja.json b/renderer/src/i18n/ja.json index 6cc72cf..3a755e9 100644 --- a/renderer/src/i18n/ja.json +++ b/renderer/src/i18n/ja.json @@ -155,5 +155,6 @@ "return": "戻る", "error": "エラー", "feedback": "フィードバック", - "waiting-mcp-server": "MCPサーバーの応答を待機中" + "waiting-mcp-server": "MCPサーバーの応答を待機中", + "parallel-tool-calls": "モデルが単一の返信で複数のツールを呼び出すことを許可する" } \ No newline at end of file diff --git a/renderer/src/i18n/ko.json b/renderer/src/i18n/ko.json index 99f41da..bb5ac07 100644 --- a/renderer/src/i18n/ko.json +++ b/renderer/src/i18n/ko.json @@ -155,5 +155,6 @@ "return": "돌아가기", "error": "오류", "feedback": "피드백", - "waiting-mcp-server": "MCP 서버 응답 대기 중" + "waiting-mcp-server": "MCP 서버 응답 대기 중", + "parallel-tool-calls": "모델이 단일 응답에서 여러 도구를 호출할 수 있도록 허용" } \ No newline at end of file diff --git a/renderer/src/i18n/ru.json b/renderer/src/i18n/ru.json index 62804ca..a757bb7 100644 --- a/renderer/src/i18n/ru.json +++ b/renderer/src/i18n/ru.json @@ -155,5 +155,6 @@ "return": "Назад", "error": "Ошибка", "feedback": "Обратная связь", - "waiting-mcp-server": "Ожидание ответа от сервера MCP" + "waiting-mcp-server": "Ожидание ответа от сервера MCP", + "parallel-tool-calls": "Разрешить модели вызывать несколько инструментов в одном ответе" } \ No newline at end of file diff --git a/renderer/src/i18n/zh-cn.json b/renderer/src/i18n/zh-cn.json index 68fe9ab..d145509 100644 --- a/renderer/src/i18n/zh-cn.json +++ b/renderer/src/i18n/zh-cn.json @@ -155,5 +155,6 @@ "return": "返回", "error": "错误", "feedback": "反馈", - "waiting-mcp-server": "等待 MCP 服务器响应" + "waiting-mcp-server": "等待 MCP 服务器响应", + "parallel-tool-calls": "允许模型在单轮回复中调用多个工具" } \ No newline at end of file diff --git a/renderer/src/i18n/zh-tw.json b/renderer/src/i18n/zh-tw.json index 77e186f..4f0ffd8 100644 --- a/renderer/src/i18n/zh-tw.json +++ b/renderer/src/i18n/zh-tw.json @@ -155,5 +155,6 @@ "return": "返回", "error": "錯誤", "feedback": "反饋", - "waiting-mcp-server": "等待MCP伺服器響應" + "waiting-mcp-server": "等待MCP伺服器響應", + "parallel-tool-calls": "允許模型在單輪回覆中調用多個工具" } \ No newline at end of file diff --git a/renderer/src/views/connect/connection-log.vue b/renderer/src/views/connect/connection-log.vue index c41fc9f..60d3b28 100644 --- a/renderer/src/views/connect/connection-log.vue +++ b/renderer/src/views/connect/connection-log.vue @@ -11,13 +11,13 @@
- {{ log.message }} + {{ log.message || '' }}
@@ -52,7 +52,7 @@ function clearLogs() {