This commit is contained in:
锦恢 2025-07-15 21:23:24 +08:00
parent 7a6b857bae
commit 63fb5d3494
17 changed files with 200 additions and 415 deletions

View File

@ -2,12 +2,13 @@
## [main] 0.1.10 ## [main] 0.1.10
- 修复 issue #48: 修复错误的引导路径。 - 修复 issue #48: 修复错误的引导路径。
- 完成引导界面的多语言。
- 支持 kimi 的 usage 计数 + 支持 kimi 的 system prompt。 - 支持 kimi 的 usage 计数 + 支持 kimi 的 system prompt。
- 实现 openmcp 工具测试的并行执行和暂停功能。 - 实现 openmcp 工具测试的并行执行和暂停功能。 https://picx.zhimg.com/80/v2-4e09958d91dcf561c578294d8b6f3349_1440w.png
- 修正 API 测速中算法,剥离为 tps + 排队时间两部分。 - 修正 API 测速中算法,剥离为 tps + 排队时间两部分。 https://picx.zhimg.com/80/v2-1cc3044a3ec3d5d21cb265dd67518ca0_1440w.png
- 大模型 api 测速目前可以自定义 prompt 了。 - 大模型 api 测速目前可以自定义 prompt 了。 https://picx.zhimg.com/80/v2-ff70af72254b82c11a941fe9cc29eeb8_1440w.png
- 实现 issue#49工具模块调试希望支持markdown渲染回显。 - 实现 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 ## [main] 0.1.9
- 增加 mook 功能可以利用随机种子或者AI生成来自动化填充测试 tool 的表单数据 - 增加 mook 功能可以利用随机种子或者AI生成来自动化填充测试 tool 的表单数据

View File

@ -16,5 +16,7 @@
"comment-plugin": "Comment Plugin", "comment-plugin": "Comment Plugin",
"preset-env-sync": "Preset environment variables synchronized successfully", "preset-env-sync": "Preset environment variables synchronized successfully",
"preset-env-sync.fail": "Failed to sync preset environment variables", "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"
} }

View File

@ -16,6 +16,6 @@
"comment-plugin": "コメントプラグイン", "comment-plugin": "コメントプラグイン",
"preset-env-sync": "プリセット環境変数の同期が完了しました", "preset-env-sync": "プリセット環境変数の同期が完了しました",
"preset-env-sync.fail": "プリセット環境変数の同期に失敗しました", "preset-env-sync.fail": "プリセット環境変数の同期に失敗しました",
"error.notOpenWorkspace": "現在、VSCode でワークスペースが開かれていません。まずワークスペース(例:フォルダーを開く)を開いてください。" "openmcp.sidebar.installed-connection.changeConnectionName.title": "変更する接続名を入力してください",
"error.connectionNameRequired": "サーバー名は必須です"
} }

View File

@ -16,5 +16,7 @@
"comment-plugin": "评论插件", "comment-plugin": "评论插件",
"preset-env-sync": "预设环境变量同步完成", "preset-env-sync": "预设环境变量同步完成",
"preset-env-sync.fail": "预设环境变量同步失败", "preset-env-sync.fail": "预设环境变量同步失败",
"error.notOpenWorkspace": "当前VScode没有打开工作区请先打开工作区例如打开文件夹" "error.notOpenWorkspace": "当前VScode没有打开工作区请先打开工作区例如打开文件夹",
"openmcp.sidebar.installed-connection.changeConnectionName.title": "输入修改的名称",
"error.connectionNameRequired": "服务器名称不能为空"
} }

View File

@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.svg" type="image/x-icon">
<link rel="stylesheet" href="/default-dark.css"> <link rel="stylesheet" href="/default-dark.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenMCP News Feature</title> <title>OpenMCP News Feature</title>

View File

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue';
const props = defineProps({ const props = defineProps({
version: { version: {
type: String, type: String,
@ -7,12 +9,32 @@ const props = defineProps({
changelogs: { changelogs: {
type: Array as () => string[], type: Array as () => string[],
default: () => [ default: () => [
'Brand new VSCode WebView adaptation, smoother experience', 'Brand new VSCode WebView adaptation, smoother experience https://example.com/image1.png',
'Support for AI Mock, toolchain visualization, and automatic topology detection', 'Support for AI Mock, toolchain visualization https://example.com/diagram.jpg and automatic topology detection',
'Multi-model concurrency, enhanced plugin capabilities' 'Multi-model concurrency, enhanced plugin capabilities https://example.com/arch.svg'
] ]
} }
}); });
//
const processedChangelogs = computed(() => {
return props.changelogs.map(log => {
// https
const imageRegex = /(https:\/\/[^\s]+?\.(?:png|jpg|jpeg|gif|svg|webp))/gi;
const images = [];
let match;
// URL
while ((match = imageRegex.exec(log)) !== null) {
images.push(match[1]);
}
// URL
const text = log.replace(imageRegex, '').replace(/\s{2,}/g, ' ').trim();
return { text, images };
});
});
</script> </script>
<template> <template>
@ -22,9 +44,16 @@ const props = defineProps({
</div> </div>
<div class="news-content"> <div class="news-content">
<ul class="news-list"> <ul class="news-list">
<li v-for="(log, index) in props.changelogs" :key="index"> <li v-for="(item, index) in processedChangelogs" :key="index">
<span class="news-badge">{{ '/' }}</span> <span class="news-badge">{{ '/' }}</span>
<span>{{ log }}</span> <div class="log-content">
<span>{{ item.text }}</span>
<div v-if="item.images.length" class="image-container">
<a v-for="(img, imgIndex) in item.images" :key="imgIndex" :href="img" target="_blank" rel="noopener">
<img :src="img" alt="Changelog image" class="changelog-image" />
</a>
</div>
</div>
</li> </li>
</ul> </ul>
<br> <br>
@ -68,6 +97,50 @@ const props = defineProps({
} }
.news-content li { .news-content li {
margin-bottom: 0.7rem; margin-bottom: 1.5rem;
display: flex;
align-items: flex-start;
}
.news-badge {
display: inline-block;
margin-right: 10px;
color: #B988D1;
font-weight: bold;
}
.log-content {
flex: 1;
}
.image-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.changelog-image {
max-height: 250px;
border-radius: 6px;
border: 1px solid var(--vscode-widget-border);
object-fit: contain;
background-color: var(--vscode-editor-background);
padding: 4px;
box-sizing: border-box;
transition: transform 0.2s ease;
}
.release-link {
color: #B988D1;
text-decoration: none;
font-weight: 500;
display: inline-block;
margin-top: 10px;
}
.release-link:hover {
text-decoration: underline;
} }
</style> </style>

View File

@ -3,8 +3,8 @@
"changelogs": [ "changelogs": [
"Add mook functionality: Automatically fill in test tool form data using random seeds or AI generation.", "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.", "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 #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.", "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 issue #45: Array type parameters are not supported.",
"Fix the issue of abnormal dialog styles when pasting multi-line conversations into the dialog box." "Fix the issue of abnormal dialog styles when pasting multi-line conversations into the dialog box."
], ],

View File

@ -2,7 +2,7 @@
"name": "openmcp", "name": "openmcp",
"displayName": "OpenMCP", "displayName": "OpenMCP",
"description": "An all in one MCP Client/TestTool", "description": "An all in one MCP Client/TestTool",
"version": "0.1.9", "version": "0.1.10",
"publisher": "kirigaya", "publisher": "kirigaya",
"private": true, "private": true,
"author": { "author": {

View File

@ -6,7 +6,7 @@
<template #title> <template #title>
<h3 class="resource-template"> <h3 class="resource-template">
<span>resources/templates/list</span> <span>resources/templates/list</span>
<span class="iconfont icon-restart" @click="reloadResources(client, { first: false })"></span> <span class="iconfont icon-restart" @click.stop="reloadResources(client, { first: false })"></span>
</h3> </h3>
</template> </template>

View File

@ -6,7 +6,7 @@
<template #title> <template #title>
<h3 class="resource-template"> <h3 class="resource-template">
<span>resources/list</span> <span>resources/list</span>
<span class="iconfont icon-restart" @click="reloadResources(client, { first: false })"></span> <span class="iconfont icon-restart" @click.stop="reloadResources(client, { first: false })"></span>
</h3> </h3>
</template> </template>

View File

@ -282,7 +282,6 @@ export class McpClient {
this.resourceTemplates = new Map<string, ResourceTemplate>(); this.resourceTemplates = new Map<string, ResourceTemplate>();
msg.resourceTemplates.forEach(template => { msg.resourceTemplates.forEach(template => {
this.resourceTemplates!.set(template.name, template); this.resourceTemplates!.set(template.name, template);
}); });
return this.resourceTemplates; return this.resourceTemplates;
} }
@ -496,7 +495,7 @@ export class McpClient {
class McpClientAdapter { class McpClientAdapter {
public clients: Reactive<McpClient[]> = []; public clients: Reactive<McpClient[]> = reactive([]);
public currentClientIndex: number = 0; public currentClientIndex: number = 0;
public refreshSignal = reactive({ value: 0 }); public refreshSignal = reactive({ value: 0 });
@ -586,7 +585,9 @@ class McpClientAdapter {
console.log('clientIndex', clientIndex); console.log('clientIndex', clientIndex);
await this.clients[clientIndex].refreshAllResources(); await this.clients[clientIndex].refreshAllResources();
this.refreshSignal.value++;
// 更新 refreshSignal所有 watch refreshSignal 的部分会发生更新
this.refreshSignal.value ++;
} else { } else {
console.error( console.error(
chalk.gray(`[${new Date().toLocaleString()}]`), chalk.gray(`[${new Date().toLocaleString()}]`),

View File

@ -44,6 +44,7 @@ export class McpServerConnectMonitor {
switch (options.connectionType) { switch (options.connectionType) {
case 'STDIO': case 'STDIO':
console.log('monitor on ' + this.filePath);
this.setupStdioMonitor(onchange); this.setupStdioMonitor(onchange);
break; break;
case 'SSE': case 'SSE':
@ -64,8 +65,6 @@ export class McpServerConnectMonitor {
try { try {
await onchange(this.uuid, this.Options); await onchange(this.uuid, this.Options);
console.log('send something');
this.sendWebviewMessage('connect/refresh', { this.sendWebviewMessage('connect/refresh', {
code: 200, code: 200,
msg: { msg: {

View File

@ -25,6 +25,21 @@ export async function updateClientMap(uuid: string, options: McpOptions): Promis
chalk.white('update client tools'), chalk.white('update client tools'),
chalk.blue(tools.tools.map(tool => tool.name).join(',')) 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 }; return { res: true };
} catch (error) { } catch (error) {
console.error('[updateClientMap] error:', error); console.error('[updateClientMap] error:', error);

View File

@ -1,6 +1,6 @@
{ {
"clientId": "ea2b1e70-1e70-5b1e705a3ac-8b1e705a3ac8921-c8921324", "clientId": "27a62b3c-2b3c-562b3c408e5-862b3c408e5800e-5800ec5e",
"currentIndex": 1, "currentIndex": 0,
"tabs": [ "tabs": [
{ {
"name": "工具", "name": "工具",
@ -42,7 +42,11 @@
], ],
"isError": false "isError": false
}, },
"currentPromptName": "translate" "currentPromptName": "translate",
"autoDetectDiagram": {
"edges": [],
"views": []
}
} }
}, },
{ {
@ -410,322 +414,6 @@
}, },
"enabled": true "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", "name": "k_get_full_page_text",
"description": "获取页面所有文本内容", "description": "获取页面所有文本内容",

View File

@ -39,6 +39,7 @@ export interface McpOptions {
name?: string; name?: string;
version?: string; version?: string;
type?: ConnectionType; type?: ConnectionType;
rename?: boolean;
[key: string]: any; [key: string]: any;
} }
@ -152,8 +153,7 @@ export function getWorkspaceConnectionConfig():IConnectionConfig| null {
const workspacePath = getWorkspacePath(); const workspacePath = getWorkspacePath();
for (let item of connection.items) { for (let item of connection.items) {
const connections = Array.isArray(item) ? item : [item]; for (let connection of detachMcpOptionAsArray(item)) {
for (let connection of connections) {
const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType; const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType;
connection.type = undefined; connection.type = undefined;
connection.connectionType = connectionType; connection.connectionType = connectionType;
@ -205,8 +205,9 @@ export function saveWorkspaceConnectionConfig(workspace: string) {
const workspacePath = getWorkspacePath(); const workspacePath = getWorkspacePath();
for (let item of connectionConfig.items) { for (let item of connectionConfig.items) {
const connections = Array.isArray(item) ? item : [item]; for (let connection of detachMcpOptionAsArray(item)) {
for (let connection of connections) { console.log(connection);
const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType; const connectionType = (connection.type || connection.connectionType).toUpperCase() as ConnectionType;
connection.type = undefined; connection.type = undefined;
connection.connectionType = connectionType; connection.connectionType = connectionType;
@ -245,20 +246,22 @@ export function updateWorkspaceConnectionConfig(
// 如果存在,替换老的 connectionItem // 如果存在,替换老的 connectionItem
if (connectionItem) { if (connectionItem) {
console.log("存在的 connection")
const index = workspaceConnectionConfig.items.indexOf(connectionItem); const index = workspaceConnectionConfig.items.indexOf(connectionItem);
if (index !== -1) { if (index !== -1) {
// 替换现有项目而不是删除后插入到开头 // check rename value
console.log("替换现有项目而不是删除后插入到开头") 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; workspaceConnectionConfig.items[index] = data;
} else { } else {
// 如果索引查找失败,则插入到第一个 // insert new one
console.log("没有找到现有项目,插入到第一个")
workspaceConnectionConfig.items.unshift(data); workspaceConnectionConfig.items.unshift(data);
} }
} else { } else {
// 没有找到现有项目,插入到第一个
console.log("没有找到现有项目,插入到第一个")
workspaceConnectionConfig.items.unshift(data); workspaceConnectionConfig.items.unshift(data);
} }
@ -286,18 +289,14 @@ export function updateInstalledConnectionConfig(
console.log('get connectionItem: ', data); console.log('get connectionItem: ', data);
// 如果存在,替换老的 connectionItem
if (connectionItem) { if (connectionItem) {
const index = installedConnectionConfig.items.indexOf(connectionItem); const index = installedConnectionConfig.items.indexOf(connectionItem);
if (index !== -1) { if (index !== -1) {
// 替换现有项目而不是删除后插入到开头
installedConnectionConfig.items[index] = data; installedConnectionConfig.items[index] = data;
} else { } else {
// 如果索引查找失败,则插入到第一个
installedConnectionConfig.items.unshift(data); installedConnectionConfig.items.unshift(data);
} }
} else { } else {
// 没有找到现有项目,插入到第一个
installedConnectionConfig.items.unshift(data); installedConnectionConfig.items.unshift(data);
} }
@ -338,7 +337,7 @@ export function getWorkspaceConnectionConfigItemByPath(absPath: string) {
const normaliseAbsPath = absPath.replace(/\\/g, '/'); const normaliseAbsPath = absPath.replace(/\\/g, '/');
for (let item of workspaceConnectionConfig.items) { for (let item of workspaceConnectionConfig.items) {
const nItem = Array.isArray(item) ? item[0] : item; const nItem = detachMcpOptionAsItem(item);
const filePath = normaliseConnectionFilePath(nItem, workspacePath); const filePath = normaliseConnectionFilePath(nItem, workspacePath);
if (filePath === normaliseAbsPath) { if (filePath === normaliseAbsPath) {
@ -359,7 +358,7 @@ export function getWorkspaceConnectionConfigItemByName(name: string) {
return null; // 如果没有工作区连接配置文件,则返回 null return null; // 如果没有工作区连接配置文件,则返回 null
} }
for (let item of workspaceConnectionConfig.items) { for (let item of workspaceConnectionConfig.items) {
const nItem = Array.isArray(item) ? item[0] : item; const nItem = detachMcpOptionAsItem(item);
if (nItem.name === name) { if (nItem.name === name) {
return item; return item;
} }
@ -376,7 +375,7 @@ export function getInstalledConnectionConfigItemByName(name: string) {
const installedConnectionConfig = getConnectionConfig(); const installedConnectionConfig = getConnectionConfig();
for (let item of installedConnectionConfig.items) { for (let item of installedConnectionConfig.items) {
const nItem = Array.isArray(item) ? item[0] : item; const nItem = detachMcpOptionAsItem(item);
if (nItem.name) { if (nItem.name) {
return item; return item;
@ -396,7 +395,7 @@ export function getInstalledConnectionConfigItemByPath(absPath: string) {
const normaliseAbsPath = absPath.replace(/\\/g, '/'); const normaliseAbsPath = absPath.replace(/\\/g, '/');
for (let item of installedConnectionConfig.items) { for (let item of installedConnectionConfig.items) {
const nItem = Array.isArray(item) ? item[0] : item; const nItem = detachMcpOptionAsItem(item);
const filePath = (nItem.filePath || '').replace(/\\/g, '/'); const filePath = (nItem.filePath || '').replace(/\\/g, '/');
if (filePath === normaliseAbsPath) { if (filePath === normaliseAbsPath) {
@ -449,3 +448,11 @@ export async function exportFile(filename: string, content: any) {
fs.writeFileSync(uri.fsPath, content, 'utf-8'); 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];
}

View File

@ -71,15 +71,13 @@ export async function changeInstalledConnectionName(item: McpOptions[] | McpOpti
// 更新连接名称 // 更新连接名称
masterNode.name = newName.trim(); masterNode.name = newName.trim();
masterNode.rename = true;
// 保存更新后的配置 // 保存更新后的配置
saveConnectionConfig(); saveConnectionConfig();
// 刷新侧边栏视图 // 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.installed-connection.refresh'); vscode.commands.executeCommand('openmcp.sidebar.installed-connection.refresh');
// 显示成功消息
vscode.window.showInformationMessage(t('connectionNameChanged', currentName, newName));
} }
export async function acquireInstalledConnection(): Promise<McpOptions[]> { export async function acquireInstalledConnection(): Promise<McpOptions[]> {

View File

@ -1,8 +1,6 @@
import { getFirstValidPathFromCommand, getWorkspaceConnectionConfig, getWorkspacePath, McpOptions, panels, saveWorkspaceConnectionConfig } from "../global.js"; import { getFirstValidPathFromCommand, getWorkspaceConnectionConfig, getWorkspacePath, McpOptions, panels, saveWorkspaceConnectionConfig } from "../global.js";
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { t } from "../i18n/index.js"; import { t } from "../i18n/index.js";
import { promisify } from 'util';
import { spawn } from 'node:child_process';
export async function deleteUserConnection(item: McpOptions[] | McpOptions) { export async function deleteUserConnection(item: McpOptions[] | McpOptions) {
// 弹出确认对话框 // 弹出确认对话框
@ -80,16 +78,16 @@ export async function changeUserConnectionName(item: McpOptions[] | McpOptions)
// 更新连接名称 // 更新连接名称
masterNode.name = newName.trim(); masterNode.name = newName.trim();
masterNode.rename = true;
vscode.window.showInformationMessage('enter here');
// 保存更新后的配置 // 保存更新后的配置
const workspacePath = getWorkspacePath(); const workspacePath = getWorkspacePath();
await saveWorkspaceConnectionConfig(workspacePath); saveWorkspaceConnectionConfig(workspacePath);
// 刷新侧边栏视图 // 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh'); vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh');
// 显示成功消息
vscode.window.showInformationMessage(t('connectionNameChanged', currentName, newName));
} }
export async function acquireUserCustomConnection(): Promise<McpOptions[]> { export async function acquireUserCustomConnection(): Promise<McpOptions[]> {