From 63fb5d349437663c8cf903c7c6e104ead9bc95b8 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Tue, 15 Jul 2025 21:23:24 +0800 Subject: [PATCH] update --- CHANGELOG.md | 11 +- l10n/bundle.l10n.en.json | 4 +- l10n/bundle.l10n.ja.json | 4 +- l10n/bundle.l10n.zh-cn.json | 4 +- news/index.html | 1 + news/src/components/WhatNews.vue | 165 ++++++--- news/src/data.json | 4 +- package.json | 2 +- .../resource/resource-list-templates.vue | 2 +- .../main-panel/resource/resource-list.vue | 2 +- renderer/src/views/connect/core.ts | 9 +- service/src/mcp/connect-monitor.service.ts | 3 +- service/src/mcp/connect.service.ts | 15 + service/tabs.my-browser.json | 326 +----------------- src/global.ts | 45 ++- src/sidebar/installed.service.ts | 4 +- src/sidebar/workspace.service.ts | 14 +- 17 files changed, 200 insertions(+), 415 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40558f6..fb661ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,13 @@ ## [main] 0.1.10 - 修复 issue #48: 修复错误的引导路径。 -- 完成引导界面的多语言。 - 支持 kimi 的 usage 计数 + 支持 kimi 的 system prompt。 -- 实现 openmcp 工具测试的并行执行和暂停功能。 -- 修正 API 测速中算法,剥离为 tps + 排队时间两部分。 -- 大模型 api 测速目前可以自定义 prompt 了。 -- 实现 issue#49,工具模块,调试希望支持markdown渲染回显。 +- 实现 openmcp 工具测试的并行执行和暂停功能。 https://picx.zhimg.com/80/v2-4e09958d91dcf561c578294d8b6f3349_1440w.png +- 修正 API 测速中算法,剥离为 tps + 排队时间两部分。 https://picx.zhimg.com/80/v2-1cc3044a3ec3d5d21cb265dd67518ca0_1440w.png +- 大模型 api 测速目前可以自定义 prompt 了。 https://picx.zhimg.com/80/v2-ff70af72254b82c11a941fe9cc29eeb8_1440w.png +- 实现 issue#49,工具模块,调试希望支持markdown渲染回显。 https://picx.zhimg.com/80/v2-5d708ccab00f33fdf63a656a0066bf23_1440w.png +- 实现 issue#54,右击服务器列表名,可以重命名服务器。 https://picx.zhimg.com/80/v2-87c2a29abdd2dd56a4d18cc4a8b946ff_1440w.png +- 修复 resources 和 prompts 有关热更新的一些问题。 ## [main] 0.1.9 - 增加 mook 功能:可以利用随机种子或者AI生成来自动化填充测试 tool 的表单数据 diff --git a/l10n/bundle.l10n.en.json b/l10n/bundle.l10n.en.json index 0bff6bc..24c79d4 100644 --- a/l10n/bundle.l10n.en.json +++ b/l10n/bundle.l10n.en.json @@ -16,5 +16,7 @@ "comment-plugin": "Comment Plugin", "preset-env-sync": "Preset environment variables synchronized successfully", "preset-env-sync.fail": "Failed to sync preset environment variables", - "error.notOpenWorkspace": "No workspace is currently open in VSCode. Please open a workspace (e.g., open a folder) first." + "error.notOpenWorkspace": "No workspace is currently open in VSCode. Please open a workspace (e.g., open a folder) first.", + "openmcp.sidebar.installed-connection.changeConnectionName.title": "Enter the new connection name", + "error.connectionNameRequired": "Server name cannot be empty" } \ No newline at end of file diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index 3b657c8..0912df2 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -16,6 +16,6 @@ "comment-plugin": "コメントプラグイン", "preset-env-sync": "プリセット環境変数の同期が完了しました", "preset-env-sync.fail": "プリセット環境変数の同期に失敗しました", - "error.notOpenWorkspace": "現在、VSCode でワークスペースが開かれていません。まずワークスペース(例:フォルダーを開く)を開いてください。" - + "openmcp.sidebar.installed-connection.changeConnectionName.title": "変更する接続名を入力してください", + "error.connectionNameRequired": "サーバー名は必須です" } \ No newline at end of file diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 9744bb9..768adb9 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -16,5 +16,7 @@ "comment-plugin": "评论插件", "preset-env-sync": "预设环境变量同步完成", "preset-env-sync.fail": "预设环境变量同步失败", - "error.notOpenWorkspace": "当前VScode没有打开工作区,请先打开工作区(例如打开文件夹)" + "error.notOpenWorkspace": "当前VScode没有打开工作区,请先打开工作区(例如打开文件夹)", + "openmcp.sidebar.installed-connection.changeConnectionName.title": "输入修改的名称", + "error.connectionNameRequired": "服务器名称不能为空" } \ No newline at end of file diff --git a/news/index.html b/news/index.html index d5efff0..c8ad7a3 100644 --- a/news/index.html +++ b/news/index.html @@ -3,6 +3,7 @@ + OpenMCP News Feature diff --git a/news/src/components/WhatNews.vue b/news/src/components/WhatNews.vue index ff877d3..5b2886f 100644 --- a/news/src/components/WhatNews.vue +++ b/news/src/components/WhatNews.vue @@ -1,73 +1,146 @@ \ No newline at end of file diff --git a/news/src/data.json b/news/src/data.json index 5878e99..f52371b 100644 --- a/news/src/data.json +++ b/news/src/data.json @@ -3,8 +3,8 @@ "changelogs": [ "Add mook functionality: Automatically fill in test tool form data using random seeds or AI generation.", "Add tool self-check functionality: Under openmcp's tool, click 'Tool Self-Check' on the right side of 'Tool Module' to enter self-check mode. In this mode, users can define the topological order of tool execution and perform automatic detection in one go.", - "Fix issue #44: Complete platform adaptation for link redirection.", - "Fix issue #36: Ensure successful startup when not opening a folder.", + "Fix issue #44: Complete platform adaptation for link redirection. https://picx.zhimg.com/80/v2-87c2a29abdd2dd56a4d18cc4a8b946ff_1440w.png", + "Fix issue #36: Ensure successful startup when not opening a folder. https://picx.zhimg.com/80/v2-87c2a29abdd2dd56a4d18cc4a8b946ff_1440w.png", "Fix issue #45: Array type parameters are not supported.", "Fix the issue of abnormal dialog styles when pasting multi-line conversations into the dialog box." ], diff --git a/package.json b/package.json index 0238644..14791d4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "openmcp", "displayName": "OpenMCP", "description": "An all in one MCP Client/TestTool", - "version": "0.1.9", + "version": "0.1.10", "publisher": "kirigaya", "private": true, "author": { 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 4bc0601..6d58441 100644 --- a/renderer/src/components/main-panel/resource/resource-list-templates.vue +++ b/renderer/src/components/main-panel/resource/resource-list-templates.vue @@ -6,7 +6,7 @@ diff --git a/renderer/src/components/main-panel/resource/resource-list.vue b/renderer/src/components/main-panel/resource/resource-list.vue index 9084126..b25a2b4 100644 --- a/renderer/src/components/main-panel/resource/resource-list.vue +++ b/renderer/src/components/main-panel/resource/resource-list.vue @@ -6,7 +6,7 @@ diff --git a/renderer/src/views/connect/core.ts b/renderer/src/views/connect/core.ts index e90be33..ff0d52b 100644 --- a/renderer/src/views/connect/core.ts +++ b/renderer/src/views/connect/core.ts @@ -279,10 +279,9 @@ export class McpClient { if (code !== 200) { return new Map(); } - this.resourceTemplates = new Map(); + this.resourceTemplates = new Map(); msg.resourceTemplates.forEach(template => { this.resourceTemplates!.set(template.name, template); - }); return this.resourceTemplates; } @@ -496,7 +495,7 @@ export class McpClient { class McpClientAdapter { - public clients: Reactive = []; + public clients: Reactive = reactive([]); public currentClientIndex: number = 0; public refreshSignal = reactive({ value: 0 }); @@ -586,7 +585,9 @@ class McpClientAdapter { console.log('clientIndex', clientIndex); await this.clients[clientIndex].refreshAllResources(); - this.refreshSignal.value++; + + // 更新 refreshSignal,所有 watch refreshSignal 的部分会发生更新 + this.refreshSignal.value ++; } else { console.error( chalk.gray(`[${new Date().toLocaleString()}]`), diff --git a/service/src/mcp/connect-monitor.service.ts b/service/src/mcp/connect-monitor.service.ts index b486354..49ef919 100644 --- a/service/src/mcp/connect-monitor.service.ts +++ b/service/src/mcp/connect-monitor.service.ts @@ -44,6 +44,7 @@ export class McpServerConnectMonitor { switch (options.connectionType) { case 'STDIO': + console.log('monitor on ' + this.filePath); this.setupStdioMonitor(onchange); break; case 'SSE': @@ -63,8 +64,6 @@ export class McpServerConnectMonitor { onChange: async (curr, prev) => { try { await onchange(this.uuid, this.Options); - - console.log('send something'); this.sendWebviewMessage('connect/refresh', { code: 200, diff --git a/service/src/mcp/connect.service.ts b/service/src/mcp/connect.service.ts index 1e7c6e8..9aa3ce9 100644 --- a/service/src/mcp/connect.service.ts +++ b/service/src/mcp/connect.service.ts @@ -25,6 +25,21 @@ export async function updateClientMap(uuid: string, options: McpOptions): Promis chalk.white('update client tools'), chalk.blue(tools.tools.map(tool => tool.name).join(',')) ); + const resourceTemplates = await client.listResourceTemplates(); + console.log( + chalk.white('update client resourceTemplates'), + chalk.blue(resourceTemplates.resourceTemplates.map(r => r.name).join(',')) + ); + const resources = await client.listResources(); + console.log( + chalk.white('update client resources'), + chalk.blue(resources.resources.map(r => r.name).join(',')) + ); + const prompts = await client.listPrompts(); + console.log( + chalk.white('update client prompts'), + chalk.blue(prompts.prompts.map(p => p.name).join(',')) + ); return { res: true }; } catch (error) { console.error('[updateClientMap] error:', error); diff --git a/service/tabs.my-browser.json b/service/tabs.my-browser.json index 72dded2..f79a844 100644 --- a/service/tabs.my-browser.json +++ b/service/tabs.my-browser.json @@ -1,6 +1,6 @@ { - "clientId": "ea2b1e70-1e70-5b1e705a3ac-8b1e705a3ac8921-c8921324", - "currentIndex": 1, + "clientId": "27a62b3c-2b3c-562b3c408e5-862b3c408e5800e-5800ec5e", + "currentIndex": 0, "tabs": [ { "name": "工具", @@ -42,7 +42,11 @@ ], "isError": false }, - "currentPromptName": "translate" + "currentPromptName": "translate", + "autoDetectDiagram": { + "edges": [], + "views": [] + } } }, { @@ -410,322 +414,6 @@ }, "enabled": true }, - { - "name": "k_get_full_page_text", - "description": "获取页面所有文本内容", - "inputSchema": { - "type": "object", - "properties": {} - }, - "enabled": true - }, - { - "name": "k_navigate", - "description": "Navigate to a URL", - "inputSchema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to" - }, - "launchOptions": { - "type": "object", - "description": "PuppeteerJS LaunchOptions. Default null. If changed and not null, browser restarts. Example: { headless: true, args: ['--no-sandbox'] }" - }, - "allowDangerous": { - "type": "boolean", - "description": "Allow dangerous LaunchOptions that reduce security. When false, dangerous args like --no-sandbox will throw errors. Default false." - } - }, - "required": [ - "url" - ] - }, - "enabled": true - }, - { - "name": "k_screenshot", - "description": "Take a screenshot of the current page or a specific element", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name for the screenshot" - }, - "selector": { - "type": "string", - "description": "CSS selector for element to screenshot" - }, - "width": { - "type": "number", - "description": "Width in pixels (default: 800)" - }, - "height": { - "type": "number", - "description": "Height in pixels (default: 600)" - } - }, - "required": [ - "name" - ] - }, - "enabled": true - }, - { - "name": "k_click", - "description": "Click an element on the page", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to click" - } - }, - "required": [ - "selector" - ] - }, - "enabled": true - }, - { - "name": "k_fill", - "description": "Fill out an input field", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for input field" - }, - "value": { - "type": "string", - "description": "Value to fill" - } - }, - "required": [ - "selector", - "value" - ] - }, - "enabled": true - }, - { - "name": "k_select", - "description": "Select an element on the page with Select tag", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to select" - }, - "value": { - "type": "string", - "description": "Value to select" - } - }, - "required": [ - "selector", - "value" - ] - }, - "enabled": true - }, - { - "name": "k_hover", - "description": "Hover an element on the page", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to hover" - } - }, - "required": [ - "selector" - ] - }, - "enabled": true - }, - { - "name": "k_evaluate", - "description": "Execute JavaScript in the browser console", - "inputSchema": { - "type": "object", - "properties": { - "script": { - "type": "string", - "description": "JavaScript code to execute" - } - }, - "required": [ - "script" - ] - }, - "enabled": true - }, - { - "name": "k_get_full_page_text", - "description": "获取页面所有文本内容", - "inputSchema": { - "type": "object", - "properties": {} - }, - "enabled": true - }, - { - "name": "k_navigate", - "description": "Navigate to a URL", - "inputSchema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to" - }, - "launchOptions": { - "type": "object", - "description": "PuppeteerJS LaunchOptions. Default null. If changed and not null, browser restarts. Example: { headless: true, args: ['--no-sandbox'] }" - }, - "allowDangerous": { - "type": "boolean", - "description": "Allow dangerous LaunchOptions that reduce security. When false, dangerous args like --no-sandbox will throw errors. Default false." - } - }, - "required": [ - "url" - ] - }, - "enabled": true - }, - { - "name": "k_screenshot", - "description": "Take a screenshot of the current page or a specific element", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name for the screenshot" - }, - "selector": { - "type": "string", - "description": "CSS selector for element to screenshot" - }, - "width": { - "type": "number", - "description": "Width in pixels (default: 800)" - }, - "height": { - "type": "number", - "description": "Height in pixels (default: 600)" - } - }, - "required": [ - "name" - ] - }, - "enabled": true - }, - { - "name": "k_click", - "description": "Click an element on the page", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to click" - } - }, - "required": [ - "selector" - ] - }, - "enabled": true - }, - { - "name": "k_fill", - "description": "Fill out an input field", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for input field" - }, - "value": { - "type": "string", - "description": "Value to fill" - } - }, - "required": [ - "selector", - "value" - ] - }, - "enabled": true - }, - { - "name": "k_select", - "description": "Select an element on the page with Select tag", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to select" - }, - "value": { - "type": "string", - "description": "Value to select" - } - }, - "required": [ - "selector", - "value" - ] - }, - "enabled": true - }, - { - "name": "k_hover", - "description": "Hover an element on the page", - "inputSchema": { - "type": "object", - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for element to hover" - } - }, - "required": [ - "selector" - ] - }, - "enabled": true - }, - { - "name": "k_evaluate", - "description": "Execute JavaScript in the browser console", - "inputSchema": { - "type": "object", - "properties": { - "script": { - "type": "string", - "description": "JavaScript code to execute" - } - }, - "required": [ - "script" - ] - }, - "enabled": true - }, { "name": "k_get_full_page_text", "description": "获取页面所有文本内容", diff --git a/src/global.ts b/src/global.ts index d86bdbc..73f4e49 100644 --- a/src/global.ts +++ b/src/global.ts @@ -39,6 +39,7 @@ export interface McpOptions { name?: string; version?: string; type?: ConnectionType; + rename?: boolean; [key: string]: any; } @@ -152,8 +153,7 @@ export function getWorkspaceConnectionConfig():IConnectionConfig| null { const workspacePath = getWorkspacePath(); for (let item of connection.items) { - const connections = Array.isArray(item) ? item : [item]; - for (let connection of connections) { + for (let connection of detachMcpOptionAsArray(item)) { const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType; connection.type = undefined; connection.connectionType = connectionType; @@ -205,8 +205,9 @@ export function saveWorkspaceConnectionConfig(workspace: string) { const workspacePath = getWorkspacePath(); for (let item of connectionConfig.items) { - const connections = Array.isArray(item) ? item : [item]; - for (let connection of connections) { + for (let connection of detachMcpOptionAsArray(item)) { + console.log(connection); + const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType; connection.type = undefined; connection.connectionType = connectionType; @@ -245,20 +246,22 @@ export function updateWorkspaceConnectionConfig( // 如果存在,替换老的 connectionItem if (connectionItem) { - console.log("存在的 connection") const index = workspaceConnectionConfig.items.indexOf(connectionItem); if (index !== -1) { - // 替换现有项目而不是删除后插入到开头 - console.log("替换现有项目而不是删除后插入到开头") + // check rename value + const oldNItem = detachMcpOptionAsItem(workspaceConnectionConfig.items[index]); + if (oldNItem.rename) { + // if renamed, reserve user defined name + const newNItem = detachMcpOptionAsItem(data); + newNItem.name = oldNItem.name; + } + workspaceConnectionConfig.items[index] = data; } else { - // 如果索引查找失败,则插入到第一个 - console.log("没有找到现有项目,插入到第一个") + // insert new one workspaceConnectionConfig.items.unshift(data); } } else { - // 没有找到现有项目,插入到第一个 - console.log("没有找到现有项目,插入到第一个") workspaceConnectionConfig.items.unshift(data); } @@ -286,18 +289,14 @@ export function updateInstalledConnectionConfig( console.log('get connectionItem: ', data); - // 如果存在,替换老的 connectionItem if (connectionItem) { const index = installedConnectionConfig.items.indexOf(connectionItem); if (index !== -1) { - // 替换现有项目而不是删除后插入到开头 installedConnectionConfig.items[index] = data; } else { - // 如果索引查找失败,则插入到第一个 installedConnectionConfig.items.unshift(data); } } else { - // 没有找到现有项目,插入到第一个 installedConnectionConfig.items.unshift(data); } @@ -338,7 +337,7 @@ export function getWorkspaceConnectionConfigItemByPath(absPath: string) { const normaliseAbsPath = absPath.replace(/\\/g, '/'); for (let item of workspaceConnectionConfig.items) { - const nItem = Array.isArray(item) ? item[0] : item; + const nItem = detachMcpOptionAsItem(item); const filePath = normaliseConnectionFilePath(nItem, workspacePath); if (filePath === normaliseAbsPath) { @@ -359,7 +358,7 @@ export function getWorkspaceConnectionConfigItemByName(name: string) { return null; // 如果没有工作区连接配置文件,则返回 null } for (let item of workspaceConnectionConfig.items) { - const nItem = Array.isArray(item) ? item[0] : item; + const nItem = detachMcpOptionAsItem(item); if (nItem.name === name) { return item; } @@ -376,7 +375,7 @@ export function getInstalledConnectionConfigItemByName(name: string) { const installedConnectionConfig = getConnectionConfig(); for (let item of installedConnectionConfig.items) { - const nItem = Array.isArray(item) ? item[0] : item; + const nItem = detachMcpOptionAsItem(item); if (nItem.name) { return item; @@ -396,7 +395,7 @@ export function getInstalledConnectionConfigItemByPath(absPath: string) { const normaliseAbsPath = absPath.replace(/\\/g, '/'); for (let item of installedConnectionConfig.items) { - const nItem = Array.isArray(item) ? item[0] : item; + const nItem = detachMcpOptionAsItem(item); const filePath = (nItem.filePath || '').replace(/\\/g, '/'); if (filePath === normaliseAbsPath) { @@ -448,4 +447,12 @@ export async function exportFile(filename: string, content: any) { if (uri) { fs.writeFileSync(uri.fsPath, content, 'utf-8'); } +} + +export function detachMcpOptionAsItem(data: McpOptions | McpOptions[]): McpOptions { + return Array.isArray(data) ? data[0] : data; +} + +export function detachMcpOptionAsArray(data: McpOptions | McpOptions[]): McpOptions[] { + return Array.isArray(data) ? data : [data]; } \ No newline at end of file diff --git a/src/sidebar/installed.service.ts b/src/sidebar/installed.service.ts index 50e0b99..5c1fa9a 100644 --- a/src/sidebar/installed.service.ts +++ b/src/sidebar/installed.service.ts @@ -71,15 +71,13 @@ export async function changeInstalledConnectionName(item: McpOptions[] | McpOpti // 更新连接名称 masterNode.name = newName.trim(); + masterNode.rename = true; // 保存更新后的配置 saveConnectionConfig(); // 刷新侧边栏视图 vscode.commands.executeCommand('openmcp.sidebar.installed-connection.refresh'); - - // 显示成功消息 - vscode.window.showInformationMessage(t('connectionNameChanged', currentName, newName)); } export async function acquireInstalledConnection(): Promise { diff --git a/src/sidebar/workspace.service.ts b/src/sidebar/workspace.service.ts index 0ec72ed..e4cacf5 100644 --- a/src/sidebar/workspace.service.ts +++ b/src/sidebar/workspace.service.ts @@ -1,8 +1,6 @@ import { getFirstValidPathFromCommand, getWorkspaceConnectionConfig, getWorkspacePath, McpOptions, panels, saveWorkspaceConnectionConfig } from "../global.js"; import * as vscode from 'vscode'; import { t } from "../i18n/index.js"; -import { promisify } from 'util'; -import { spawn } from 'node:child_process'; export async function deleteUserConnection(item: McpOptions[] | McpOptions) { // 弹出确认对话框 @@ -80,16 +78,16 @@ export async function changeUserConnectionName(item: McpOptions[] | McpOptions) // 更新连接名称 masterNode.name = newName.trim(); + masterNode.rename = true; + + vscode.window.showInformationMessage('enter here'); // 保存更新后的配置 - const workspacePath = getWorkspacePath(); - await saveWorkspaceConnectionConfig(workspacePath); - + const workspacePath = getWorkspacePath(); + saveWorkspaceConnectionConfig(workspacePath); + // 刷新侧边栏视图 vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh'); - - // 显示成功消息 - vscode.window.showInformationMessage(t('connectionNameChanged', currentName, newName)); } export async function acquireUserCustomConnection(): Promise {