Compare commits

...

4 Commits

Author SHA1 Message Date
64584c6f6d modify about page 2025-06-11 00:45:29 +08:00
c31a6a39c7 update readme 2025-06-10 02:29:42 +08:00
9cb6387fe2 update readme 2025-06-10 02:26:25 +08:00
e4bf1c8fd6 update readme 2025-06-10 02:20:13 +08:00
26 changed files with 414 additions and 1240 deletions

View File

@ -1,34 +0,0 @@
{
"items": [
[
{
"connectionType": "STDIO",
"command": "mcp",
"args": [
"run",
"main.py"
],
"url": "",
"cwd": "{workspace}/servers",
"oauth": "",
"clientName": "openmcp.connect.STDIO",
"clientVersion": "0.0.1",
"env": {
"HOME": "/Users/bytedance",
"LOGNAME": "bytedance",
"PATH": "/opt/homebrew/opt/openjdk@11/bin:/Users/bytedance/Downloads/neo4j-community-4.4.44/bin:/Users/bytedance/.local/bin:/Users/bytedance/.nvm/versions/node/v22.14.0/bin:/Users/bytedance/miniconda3/bin:/Users/bytedance/miniconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/usr/local/go/bin:/opt/puppetlabs/bin:/Users/bytedance/.cargo/bin:/Users/bytedance/Downloads/Visual Studio Code.app/Contents/Resources/app/bin/:/Applications/Trae CN.app/Contents/Resources/app/bin/lib",
"SHELL": "/bin/zsh",
"TERM": "xterm-256color",
"USER": "bytedance"
},
"serverInfo": {
"name": "锦恢的 MCP Server",
"version": "1.5.0"
},
"filePath": "{workspace}/servers/main.py",
"name": "锦恢的 MCP Server",
"version": "1.5.0"
}
]
]
}

View File

@ -11,6 +11,6 @@
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off", "typescript.tsc.autoDetect": "off",
"i18n-haru.root": "l10n", "i18n-haru.root": "./renderer/src/i18n",
"i18n-haru.main": "zh" "i18n-haru.main": "zh"
} }

File diff suppressed because one or more lines are too long

View File

@ -1,387 +0,0 @@
{
"currentIndex": 3,
"tabs": [
{
"name": "交互测试",
"icon": "icon-robot",
"type": "blank",
"componentIndex": 3,
"storage": {
"messages": [
{
"role": "user",
"content": "总结  https://asoca.grand-challenge.org/ ",
"extraInfo": {
"created": 1747379137481,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_2z36dkpt4m5jaioqjsbjabiw",
"index": 0,
"type": "function",
"function": {
"name": "k_navigate",
"arguments": "{\"url\":\"https://asoca.grand-challenge.org/\"}"
}
}
],
"extraInfo": {
"created": 1747379138355,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 0,
"tool_call_id": "call_2z36dkpt4m5jaioqjsbjabiw",
"content": [
{
"type": "text",
"text": "Navigated to https://asoca.grand-challenge.org/"
}
],
"extraInfo": {
"created": 1747379139028,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "assistant",
"content": "现在我将总结 https://asoca.grand-challenge.org/ 的内容。\n\n首先我需要浏览页面并提取相关信息。接下来我将执行以下步骤\n\n1. 获取页面的标题和主要描述。\n2. 提取页面中的关键信息,如项目目标、参与方式、时间安排等。\n3. 总结页面的主要内容和目的。\n\n让我开始执行这些步骤。",
"tool_calls": [
{
"id": "call_zv6y2wsmzqn9ei7y8oywt75r",
"index": 0,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"document.title\"}"
}
},
{
"id": "call_uzg4bj50l2ekjaonrkj8r852",
"index": 1,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"document.querySelector('meta[name=\\\"description\\\"]').content\"}"
}
},
{
"id": "call_q3jqivcv8vgfpmk4u7w9k9au",
"index": 2,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"Array.from(document.querySelectorAll('h1, h2, h3, p')).map(el => el.textContent.trim()).join('\\\\n')\"}"
}
}
],
"extraInfo": {
"created": 1747379142638,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 0,
"tool_call_id": "call_zv6y2wsmzqn9ei7y8oywt75r",
"content": [
{
"type": "text",
"text": "Execution result:\n\"ERROR: The request could not be satisfied\"\n\nConsole output:\n"
}
],
"extraInfo": {
"created": 1747379142650,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 1,
"tool_call_id": "call_uzg4bj50l2ekjaonrkj8r852",
"content": [
{
"type": "text",
"text": "Script execution failed: Cannot read properties of null (reading 'content')"
}
],
"extraInfo": {
"created": 1747379142656,
"state": "tool call failed",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 2,
"tool_call_id": "call_q3jqivcv8vgfpmk4u7w9k9au",
"content": [
{
"type": "text",
"text": "Execution result:\n\"403 ERROR\\nThe request could not be satisfied.\"\n\nConsole output:\n"
}
],
"extraInfo": {
"created": 1747379142664,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_w7iq0mszlm46ooo06w9fvri4",
"index": 0,
"type": "function",
"function": {
"name": "k_navigate",
"arguments": "{\"url\":\"https://asoca.grand-challenge.org/\",\"launchOptions\":{\"headless\":false,\"args\":[\"--no-sandbox\"]},\"allowDangerous\":true}"
}
}
],
"extraInfo": {
"created": 1747379144069,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 0,
"tool_call_id": "call_w7iq0mszlm46ooo06w9fvri4",
"content": [
{
"type": "text",
"text": "Navigated to https://asoca.grand-challenge.org/"
}
],
"extraInfo": {
"created": 1747379147016,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_qelzom3lpyo7skuil4b469t9",
"index": 0,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"document.title\"}"
}
},
{
"id": "call_wtla8rzqnes1gffk7wieubxk",
"index": 1,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"document.querySelector('meta[name=\\\"description\\\"]').content\"}"
}
},
{
"id": "call_z6wcwspc9lqk4w3sfknv30um",
"index": 2,
"type": "function",
"function": {
"name": "k_evaluate",
"arguments": "{\"script\":\"Array.from(document.querySelectorAll('h1, h2, h3, p')).map(el => el.textContent.trim()).join('\\\\n')\"}"
}
}
],
"extraInfo": {
"created": 1747379148961,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 0,
"tool_call_id": "call_qelzom3lpyo7skuil4b469t9",
"content": [
{
"type": "text",
"text": "Execution result:\n\"\"\n\nConsole output:\n"
}
],
"extraInfo": {
"created": 1747379149424,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 1,
"tool_call_id": "call_wtla8rzqnes1gffk7wieubxk",
"content": [
{
"type": "text",
"text": "Script execution failed: Cannot read properties of null (reading 'content')"
}
],
"extraInfo": {
"created": 1747379149428,
"state": "tool call failed",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "tool",
"index": 2,
"tool_call_id": "call_z6wcwspc9lqk4w3sfknv30um",
"content": [
{
"type": "text",
"text": "Execution result:\n\"\"\n\nConsole output:\n"
}
],
"extraInfo": {
"created": 1747379149432,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
},
{
"role": "assistant",
"content": " https://asoca.grand-challenge.org/ \n\n1. ****\n2. ****\n3. **使**\n\n",
"extraInfo": {
"created": 1747379151760,
"state": "success",
"serverName": "Huoshan DeepSeek"
}
}
],
"settings": {
"modelIndex": 7,
"enableTools": [
{
"name": "k_navigate",
"description": "Navigate to a URL",
"enabled": true
},
{
"name": "k_screenshot",
"description": "Take a screenshot of the current page or a specific element",
"enabled": true
},
{
"name": "k_click",
"description": "Click an element on the page",
"enabled": true
},
{
"name": "k_fill",
"description": "Fill out an input field",
"enabled": true
},
{
"name": "k_select",
"description": "Select an element on the page with Select tag",
"enabled": true
},
{
"name": "k_hover",
"description": "Hover an element on the page",
"enabled": true
},
{
"name": "k_evaluate",
"description": "Execute JavaScript in the browser console",
"enabled": true
}
],
"enableWebSearch": false,
"temperature": 0.7,
"contextLength": 20,
"systemPrompt": ""
}
}
},
{
"name": "工具",
"icon": "icon-tool",
"type": "tool",
"componentIndex": 2,
"storage": {
"currentToolName": "k_navigate",
"formData": {
"url": "https://asoca.grand-challenge.org/",
"launchOptions": {
"headless": false
},
"allowDangerous": false
},
"lastToolCallResponse": {
"content": [
{
"type": "text",
"text": "Navigated to https://asoca.grand-challenge.org/"
}
],
"isError": false
}
}
},
{
"name": "资源",
"icon": "icon-file",
"type": "blank",
"componentIndex": 0,
"storage": {
"formData": {},
"currentType": "resource",
"currentResourceName": "Browser console logs",
"lastResourceReadResponse": {
"contents": [
{
"uri": "console://logs",
"mimeType": "text/plain",
"text": "[warn] Error with Permissions-Policy header: Unrecognized feature: 'ambient-light-sensor'.\n[warn] Error with Permissions-Policy header: Unrecognized feature: 'document-domain'.\n[warn] Error with Permissions-Policy header: Unrecognized feature: 'ambient-light-sensor'.\n[warn] Error with Permissions-Policy header: Unrecognized feature: 'document-domain'.\n[error] Failed to load resource: the server responded with a status of 403 ()\n[error] Failed to load resource: the server responded with a status of 403 ()"
}
]
}
}
},
{
"name": "工具",
"icon": "icon-tool",
"type": "blank",
"componentIndex": 2,
"storage": {
"formData": {
"script": "document.body.innerText"
},
"currentToolName": "k_evaluate",
"lastToolCallResponse": {
"content": [
{
"type": "text",
"text": "Execution result:\n\"\"\n\nConsole output:\n"
}
],
"isError": false
}
}
}
]
}

View File

@ -1,30 +0,0 @@
{
"clientId": "737fbd1e-bd1e-5fbd1ee197b-8fbd1ee197b1295-b1295bef",
"currentIndex": 0,
"tabs": [
{
"name": "工具",
"icon": "icon-tool",
"type": "blank",
"componentIndex": 2,
"storage": {
"activeNames": [
0
],
"formData": {
"city_code": 101210101
},
"currentToolName": "get_weather_by_city_code",
"lastToolCallResponse": {
"content": [
{
"type": "text",
"text": "CityWeather(city_name_en='hangzhou', city_name_cn='杭州', city_code='101210101', temp='24.2', wd='', ws='', sd='64%', aqi='54', weather='阴')"
}
],
"isError": false
}
}
}
]
}

152
README.md
View File

@ -2,76 +2,73 @@
<img src="./icons/openmcp.png" height="200px"/> <img src="./icons/openmcp.png" height="200px"/>
<h3>OpenMCP: 一体化 MCP Server 调试器</h3> <h3>OpenMCP: All you need for MCP Development</h3>
<a href="https://kirigaya.cn/openmcp" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;"> 📄 OpenMCP 文档网站</a> English | [中文](./README.zh.md)
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: #CB81DA; color: white; border-radius: .5em; text-decoration: none;">👉 加入 OpenMCP正式级技术组</a> <a href="https://kirigaya.cn/openmcp" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;"> 📄 OpenMCP Documentation</a>
<a href="https://discord.gg/SKTZRf6NzU" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;"> 加入 OpenMCP Discord频道</a> <a href="https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: #CB81DA; color: white; border-radius: .5em; text-decoration: none;">OpenMCP QQ Group</a>
<a href="https://discord.gg/SKTZRf6NzU" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;">OpenMCP Discord Channel</a>
</div> </div>
## OpenMCP ## OpenMCP
一款用于 MCP 服务端调试的一体化 vscode/trae/cursor 插件。 An all-in-one vscode/trae/cursor plugin for MCP server debugging.
[![IMAGE ALT TEXT HERE](https://pic1.zhimg.com/80/v2-951261f789708621a2c34faa5fa6f330_1440w.png)](https://www.youtube.com/watch?v=S7igsEhcLiw)
### [👆 Full Video](https://www.youtube.com/watch?v=S7igsEhcLiw)
<video src="https://github.com/user-attachments/assets/ab214d58-b77c-4bd3-8b6e-55552f4036ff" width="100%"></video> Integrated Inspector + MCP client basic functions, combining development and testing into one.
<video src="https://github.com/user-attachments/assets/c17a4ad7-83b4-47ff-8627-85b57ad18940" width="100%"></video>
集成 Inspector + MCP 客户端基础功能,开发测试一体化。
![](./icons/openmcp.welcome.png) ![](./icons/openmcp.welcome.png)
进行资源协议、工具、Prompt 的 MCP 服务器测试。 Test resource protocols, tools, and Prompts for MCP servers.
![](./icons/openmcp.resource.png) ![](./icons/openmcp.resource.png)
测试完成的工具可以放入 「交互测试」 模块之间进行大模型交互测试。 Tested tools can be placed in the "Interactive Testing" module for large model interaction testing.
![](./icons/openmcp.chatbot.png) ![](./icons/openmcp.chatbot.png)
完整的项目级管理面板,更加方便的进行项目和全局的 mcp 项目管理。 Complete project-level management panel for easier MCP project management at both project and global levels.
![](./icons/openmcp.management.png) ![](./icons/openmcp.management.png)
支持多种大模型 Supports multiple large models
![](./icons/openmcp.support.llm.png) ![](./icons/openmcp.support.llm.png)
## TODO ## TODO
## 需求规划 ## Feature Roadmap
| 所在模块 | 需求内容 | 功能优先级 | 当前状态 | 修复优先级 | | Module | Feature | Priority | Status | Fix Priority |
|---------|---------|--------|---------|-----------| |---------|---------|--------|---------|-----------|
| `all` | 完成最基本的各类基础设施 | `完整版本` | 100% | `Done` | | `all` | Complete basic infrastructure | `Full Version` | 100% | `Done` |
| `render` | chat 模式下支持进行成本分析 | `迭代版本` | 100% | `Done` | | `render` | Support cost analysis in chat mode | `Iteration` | 100% | `Done` |
| `ext` | 支持基本的 MCP 项目管理 | `迭代版本` | 100% | `P0` | | `ext` | Support basic MCP project management | `Iteration` | 100% | `P0` |
| `service` | 支持自定义支持 openai 接口协议的大模型接入 | `完整版本` | 100% | `Done` | | `service` | Support custom OpenAI-compatible large model integration | `Full Version` | 100% | `Done` |
| `service` | 支持自定义接口协议的大模型接入 | `MVP` | 0% | `P1` | | `service` | Support custom protocol large model integration | `MVP` | 0% | `P1` |
| `all` | 支持同时调试多个 MCP Server | `MVP` | 100% | `P0` | | `all` | Support debugging multiple MCP Servers simultaneously | `MVP` | 100% | `P0` |
| `all` | 支持通过大模型进行在线验证 | `迭代版本` | 100% | `Done` | | `all` | Support online verification via large models | `Iteration` | 100% | `Done` |
| `all` | 支持对用户对应服务器的调试工作内容进行保存 | `迭代版本` | 100% | `Done` | | `all` | Support saving user's server debugging work | `Iteration` | 100% | `Done` |
| `render` | 高危操作权限确认 | `MVP` | 0% | `P1` | | `render` | High-risk operation permission confirmation | `MVP` | 0% | `P1` |
| `service` | 对于连接的 mcp server 进行热更新 | `MVP` | 0% | `P1` | | `service` | Hot update for connected MCP servers | `MVP` | 0% | `P1` |
| `service` | 系统配置信息云同步 | `MVP` | 0% | `P1` | | `service` | Cloud sync for system configuration | `MVP` | 0% | `P1` |
| `all` | 系统提示词管理模块 | `迭代版本` | 100% | `Done` | | `all` | System prompt management module | `Iteration` | 100% | `Done` |
| `service` | 工具 wise 的日志系统 | `MVP` | 0% | `P1` | | `service` | Tool-wise logging system | `MVP` | 0% | `P1` |
| `service` | 自带 OCR 进行字符识别 | `迭代版本` | 100% | `Done` | | `service` | Built-in OCR for character recognition | `Iteration` | 100% | `Done` |
## Project Concept
## 项目概念 OpenMCP adopts a layered modular design. By assembling different modules, it can be implemented in different modes on different platforms.
openmcp 采用分层模块化设计,通过组装不同的模块,可以将它实现成不同平台上的不同模式。
```mermaid ```mermaid
flowchart TD flowchart TD
subgraph OpenMCP核心组件 subgraph OpenMCP Core Components
renderer[Renderer] renderer[Renderer]
openmcpservice[OpenMCPService] openmcpservice[OpenMCPService]
end end
@ -82,82 +79,77 @@ flowchart TD
nginx[Nginx] nginx[Nginx]
end end
subgraph OpenMCP_插件["OpenMCP 插件"] subgraph OpenMCP_Plugin["OpenMCP Plugin"]
renderer renderer
openmcpservice openmcpservice
vscode[VSCode 插件代码] vscode[VSCode Plugin Code]
end end
subgraph OpenMCP_App["OpenMCP App"] subgraph OpenMCP_App["OpenMCP App"]
renderer renderer
openmcpservice openmcpservice
electron[Electron 代码] electron[Electron Code]
end end
subgraph QQ机器人["基于 OpenMCP 的 QQ 机器人"] subgraph QQBot["OpenMCP-based QQ Bot"]
lagrange[Lagrange.OneBot] lagrange[Lagrange.OneBot]
openmcpservice openmcpservice
end end
%% 依赖关系 %% Dependencies
OpenMCP_Web -->|前端渲染| renderer OpenMCP_Web -->|Frontend Rendering| renderer
OpenMCP_Web -->|后端服务| openmcpservice OpenMCP_Web -->|Backend Service| openmcpservice
OpenMCP_Web -->|反向代理| nginx OpenMCP_Web -->|Reverse Proxy| nginx
OpenMCP_插件 -->|UI 界面| renderer OpenMCP_Plugin -->|UI Interface| renderer
OpenMCP_插件 -->|核心逻辑| openmcpservice OpenMCP_Plugin -->|Core Logic| openmcpservice
OpenMCP_插件 -->|集成开发| vscode OpenMCP_Plugin -->|IDE Integration| vscode
OpenMCP_App -->|前端界面| renderer OpenMCP_App -->|Frontend UI| renderer
OpenMCP_App -->|本地服务| openmcpservice OpenMCP_App -->|Local Service| openmcpservice
OpenMCP_App -->|桌面封装| electron OpenMCP_App -->|Desktop Packaging| electron
QQ机器人 -->|协议适配| lagrange QQBot -->|Protocol Adaptation| lagrange
QQ机器人 -->|业务逻辑| openmcpservice QQBot -->|Business Logic| openmcpservice
``` ```
## Development
- renderer : Frontend UI definitions
- service : Test components for renderer , including a simple forwarding layer
- src : VSCode plugin definitions
--- ### Renderer & Service Development
## Dev
- `renderer`: 前端 UI 的定义
- `service`: 测试 `renderer` 的部分,包含一个简易的转发层
- `src`: vscode 插件端定义
### Renderer & Service Dev
```mermaid ```mermaid
flowchart LR flowchart LR
D[renderer] <--> A[Dev Server] <--ws--> B[service] D[renderer] <--> A[Dev Server] 
B <--mcp--> m(MCP Server) <--ws--> B[service]
B <--mcp--> m(MCP Server)
``` ```
Project setup:
配置项目
```bash ```bash
npm run setup npm run setup
``` ```
Start dev server:
启动 dev server
```bash ```bash
npm run dev npm run dev
``` ```
Port usage: 8282 (renderer) + 8081 (service)
> 端口占用: 8282 (renderer) + 8081 (service) ### Extension Development
### Extention Dev
```mermaid ```mermaid
flowchart LR flowchart LR
D[renderer] <--> A[extention.ts] <--> B[service] D[renderer] <--> A[extention.ts] <--> B
B <--mcp--> m(MCP Server) [service]
B <--mcp--> m(MCP Server)
``` ```
负载部署 Build for deployment:
```bash ```bash
npm run build npm run build
``` ```
Then just press F5, いただきます (Let's begin)
and just press f5, いただきます

162
README.zh.md Normal file
View File

@ -0,0 +1,162 @@
<div align="center">
<img src="./icons/openmcp.png" height="200px"/>
<h3>OpenMCP: 一体化 MCP Server 调试器</h3>
[English](./README.md) | 中文
<a href="https://kirigaya.cn/openmcp" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;"> 📄 OpenMCP 文档网站</a>
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: #CB81DA; color: white; border-radius: .5em; text-decoration: none;">OpenMCP QQ 讨论群</a>
<a href="https://discord.gg/SKTZRf6NzU" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;">OpenMCP Discord 频道</a>
</div>
## OpenMCP
一款用于 MCP 服务端调试的一体化 vscode/trae/cursor 插件。
[![IMAGE ALT TEXT HERE](https://pic1.zhimg.com/80/v2-951261f789708621a2c34faa5fa6f330_1440w.png)](https://www.bilibili.com/video/BV1MFTBzpEtZ/?vd_source=3f248073d6ebdb61308992901b606f24)
### [👆 完整视频](https://www.youtube.com/watch?v=S7igsEhcLiw)
集成 Inspector + MCP 客户端基础功能,开发测试一体化。
![](./icons/openmcp.welcome.png)
进行资源协议、工具、Prompt 的 MCP 服务器测试。
![](./icons/openmcp.resource.png)
测试完成的工具可以放入 「交互测试」 模块之间进行大模型交互测试。
![](./icons/openmcp.chatbot.png)
完整的项目级管理面板,更加方便的进行项目和全局的 mcp 项目管理。
![](./icons/openmcp.management.png)
支持多种大模型
![](./icons/openmcp.support.llm.png)
## TODO
## 需求规划
| 所在模块 | 需求内容 | 功能优先级 | 当前状态 | 修复优先级 |
|---------|---------|--------|---------|-----------|
| `all` | 完成最基本的各类基础设施 | `完整版本` | 100% | `Done` |
| `render` | chat 模式下支持进行成本分析 | `迭代版本` | 100% | `Done` |
| `ext` | 支持基本的 MCP 项目管理 | `迭代版本` | 100% | `P0` |
| `service` | 支持自定义支持 openai 接口协议的大模型接入 | `完整版本` | 100% | `Done` |
| `service` | 支持自定义接口协议的大模型接入 | `MVP` | 0% | `P1` |
| `all` | 支持同时调试多个 MCP Server | `MVP` | 100% | `P0` |
| `all` | 支持通过大模型进行在线验证 | `迭代版本` | 100% | `Done` |
| `all` | 支持对用户对应服务器的调试工作内容进行保存 | `迭代版本` | 100% | `Done` |
| `render` | 高危操作权限确认 | `MVP` | 0% | `P1` |
| `service` | 对于连接的 mcp server 进行热更新 | `MVP` | 0% | `P1` |
| `service` | 系统配置信息云同步 | `MVP` | 0% | `P1` |
| `all` | 系统提示词管理模块 | `迭代版本` | 100% | `Done` |
| `service` | 工具 wise 的日志系统 | `MVP` | 0% | `P1` |
| `service` | 自带 OCR 进行字符识别 | `迭代版本` | 100% | `Done` |
## 项目概念
openmcp 采用分层模块化设计,通过组装不同的模块,可以将它实现成不同平台上的不同模式。
```mermaid
flowchart TD
subgraph OpenMCP核心组件
renderer[Renderer]
openmcpservice[OpenMCPService]
end
subgraph OpenMCP_Web["OpenMCP Web"]
renderer
openmcpservice
nginx[Nginx]
end
subgraph OpenMCP_插件["OpenMCP 插件"]
renderer
openmcpservice
vscode[VSCode 插件代码]
end
subgraph OpenMCP_App["OpenMCP App"]
renderer
openmcpservice
electron[Electron 代码]
end
subgraph QQ机器人["基于 OpenMCP 的 QQ 机器人"]
lagrange[Lagrange.OneBot]
openmcpservice
end
%% 依赖关系
OpenMCP_Web -->|前端渲染| renderer
OpenMCP_Web -->|后端服务| openmcpservice
OpenMCP_Web -->|反向代理| nginx
OpenMCP_插件 -->|UI 界面| renderer
OpenMCP_插件 -->|核心逻辑| openmcpservice
OpenMCP_插件 -->|集成开发| vscode
OpenMCP_App -->|前端界面| renderer
OpenMCP_App -->|本地服务| openmcpservice
OpenMCP_App -->|桌面封装| electron
QQ机器人 -->|协议适配| lagrange
QQ机器人 -->|业务逻辑| openmcpservice
```
---
## Dev
- `renderer`: 前端 UI 的定义
- `service`: 测试 `renderer` 的部分,包含一个简易的转发层
- `src`: vscode 插件端定义
### Renderer & Service Dev
```mermaid
flowchart LR
D[renderer] <--> A[Dev Server] <--ws--> B[service]
B <--mcp--> m(MCP Server)
```
配置项目
```bash
npm run setup
```
启动 dev server
```bash
npm run dev
```
> 端口占用: 8282 (renderer) + 8081 (service)
### Extention Dev
```mermaid
flowchart LR
D[renderer] <--> A[extention.ts] <--> B[service]
B <--mcp--> m(MCP Server)
```
负载部署
```bash
npm run build
```
and just press f5, いただきます

View File

@ -13,5 +13,7 @@
"read-document": "Read documentation", "read-document": "Read documentation",
"report-issue": "Report a problem", "report-issue": "Report a problem",
"join-project": "Participate in the project", "join-project": "Participate in the project",
"comment-plugin": "Comment Plugin" "comment-plugin": "Comment Plugin",
"preset-env-sync": "Preset environment variables synchronized successfully",
"preset-env-sync.fail": "Failed to sync preset environment variables"
} }

View File

@ -13,5 +13,7 @@
"read-document": "ドキュメントを読む", "read-document": "ドキュメントを読む",
"report-issue": "問題を報告", "report-issue": "問題を報告",
"join-project": "プロジェクトに参加する", "join-project": "プロジェクトに参加する",
"comment-plugin": "コメントプラグイン" "comment-plugin": "コメントプラグイン",
"preset-env-sync": "プリセット環境変数の同期が完了しました",
"preset-env-sync.fail": "プリセット環境変数の同期に失敗しました"
} }

View File

@ -13,5 +13,7 @@
"read-document": "阅读文档", "read-document": "阅读文档",
"report-issue": "报告问题", "report-issue": "报告问题",
"join-project": "参与项目", "join-project": "参与项目",
"comment-plugin": "评论插件" "comment-plugin": "评论插件",
"preset-env-sync": "预设环境变量同步完成",
"preset-env-sync.fail": "预设环境变量同步失败"
} }

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "openmcp", "name": "openmcp",
"version": "0.1.4", "version": "0.1.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "openmcp", "name": "openmcp",
"version": "0.1.4", "version": "0.1.5",
"workspaces": [ "workspaces": [
"service", "service",
"renderer" "renderer"

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4870215 */ font-family: "iconfont"; /* Project id 4870215 */
src: url('iconfont.woff2?t=1748859145515') format('woff2'), src: url('iconfont.woff2?t=1749572305505') format('woff2'),
url('iconfont.woff?t=1748859145515') format('woff'), url('iconfont.woff?t=1749572305505') format('woff'),
url('iconfont.ttf?t=1748859145515') format('truetype'); url('iconfont.ttf?t=1749572305505') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-wendang:before {
content: "\e61b";
}
.icon-proxy:before { .icon-proxy:before {
content: "\e723"; content: "\e723";
} }

Binary file not shown.

View File

@ -172,5 +172,17 @@
"read-document": "قراءة الوثائق", "read-document": "قراءة الوثائق",
"report-issue": "الإبلاغ عن مشكلة", "report-issue": "الإبلاغ عن مشكلة",
"join-project": "المشاركة في المشروع", "join-project": "المشاركة في المشروع",
"comment-plugin": "ملحق التعليقات" "comment-plugin": "ملحق التعليقات",
"preset-env-sync.success": "تم مزامنة متغيرات البيئة المحددة مسبقًا",
"preset-env-sync.fail": "فشل مزامنة متغيرات البيئة المحددة مسبقًا",
"drag-to-fill-connect-parameters": "اسحب لملء معلمات الاتصال",
"connect-success": "تم الاتصال بنجاح",
"connect-fail": "فشل الاتصال",
"preset": "مسبق",
"openmcp-document": "الوثائق الرسمية لـ OpenMCP",
"star-our-project": "نجم مشروعنا",
"document": "الوثائق الرسمية",
"join-discussion": "انضم إلى مجموعة النقاش",
"comment-for-us": "اكتب تقييمًا لنا!",
"openmcp-developed-by": "OpenMCP Client {version} تم تطويره بواسطة {author}"
} }

View File

@ -172,5 +172,17 @@
"read-document": "Dokumentation lesen", "read-document": "Dokumentation lesen",
"report-issue": "Problem melden", "report-issue": "Problem melden",
"join-project": "Am Projekt teilnehmen", "join-project": "Am Projekt teilnehmen",
"comment-plugin": "Kommentar-Plugin" "comment-plugin": "Kommentar-Plugin",
"preset-env-sync.success": "Vordefinierte Umgebungsvariablen synchronisiert",
"preset-env-sync.fail": "Synchronisierung der vordefinierten Umgebungsvariablen fehlgeschlagen",
"drag-to-fill-connect-parameters": "Ziehen Sie die Verbindungsparameter",
"connect-success": "Erfolgreich verbunden",
"connect-fail": "Verbindungsfehler",
"preset": "Voreinstellung",
"openmcp-document": "OpenMCP offizielle Dokumentation",
"star-our-project": "Star unser Projekt",
"document": "Offizielle Dokumentation",
"join-discussion": "Diskussionsgruppe beitreten",
"comment-for-us": "Schreiben Sie eine Bewertung für uns!",
"openmcp-developed-by": "OpenMCP Client {version} entwickelt von {author}"
} }

View File

@ -158,5 +158,17 @@
"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", "parallel-tool-calls": "Allow the model to call multiple tools in a single reply",
"proxy-server": "Proxy server", "proxy-server": "Proxy server",
"update-model-list": "Update model list" "update-model-list": "Update model list",
"preset-env-sync.success": "Preset environment variables synchronized",
"preset-env-sync.fail": "Preset environment variables synchronization failed",
"drag-to-fill-connect-parameters": "Drag to fill connection parameters",
"connect-success": "Connected successfully",
"connect-fail": "Connection failed",
"preset": "Preset",
"openmcp-document": "OpenMCP official documentation",
"star-our-project": "Star our project",
"document": "Official documentation",
"join-discussion": "Join the discussion group",
"comment-for-us": "Write a review for us!",
"openmcp-developed-by": "OpenMCP Client {version} developed by {author}"
} }

View File

@ -172,5 +172,17 @@
"read-document": "Lire la documentation", "read-document": "Lire la documentation",
"report-issue": "Signaler un problème", "report-issue": "Signaler un problème",
"join-project": "Participer au projet", "join-project": "Participer au projet",
"comment-plugin": "Plugin de commentaires" "comment-plugin": "Plugin de commentaires",
"preset-env-sync.success": "Variables d'environnement prédéfinies synchronisées",
"preset-env-sync.fail": "Échec de la synchronisation des variables d'environnement prédéfinies",
"drag-to-fill-connect-parameters": "Faites glisser pour remplir les paramètres de connexion",
"connect-success": "Connexion réussie",
"connect-fail": "Échec de la connexion",
"preset": "Préréglage",
"openmcp-document": "Documentation officielle d'OpenMCP",
"star-our-project": "Star notre projet",
"document": "Documentation officielle",
"join-discussion": "Rejoindre le groupe de discussion",
"comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}"
} }

View File

@ -158,5 +158,17 @@
"waiting-mcp-server": "MCPサーバーの応答を待機中", "waiting-mcp-server": "MCPサーバーの応答を待機中",
"parallel-tool-calls": "モデルが単一の返信で複数のツールを呼び出すことを許可する", "parallel-tool-calls": "モデルが単一の返信で複数のツールを呼び出すことを許可する",
"proxy-server": "プロキシサーバー", "proxy-server": "プロキシサーバー",
"update-model-list": "モデルリストを更新" "update-model-list": "モデルリストを更新",
"preset-env-sync.success": "プリセット環境変数の同期が完了しました",
"preset-env-sync.fail": "プリセット環境変数の同期に失敗しました",
"drag-to-fill-connect-parameters": "接続パラメータを入力するためにドラッグしてください",
"connect-success": "接続に成功しました",
"connect-fail": "接続に失敗しました",
"preset": "プリセット",
"openmcp-document": "OpenMCP公式ドキュメント",
"star-our-project": "私たちのプロジェクトをスター",
"document": "公式ドキュメント",
"join-discussion": "ディスカッショングループに参加",
"comment-for-us": "私たちのためにレビューを書いてください!",
"openmcp-developed-by": "OpenMCP Client {version} は {author} によって開発されました"
} }

View File

@ -172,5 +172,17 @@
"read-document": "문서 읽기", "read-document": "문서 읽기",
"report-issue": "문제 신고", "report-issue": "문제 신고",
"join-project": "프로젝트 참여", "join-project": "프로젝트 참여",
"comment-plugin": "댓글 플러그인" "comment-plugin": "댓글 플러그인",
"preset-env-sync.success": "사전 설정 환경 변수 동기화 완료",
"preset-env-sync.fail": "사전 설정된 환경 변수 동기화 실패",
"drag-to-fill-connect-parameters": "연결 매개변수를 채우려면 드래그하세요",
"connect-success": "성공적으로 연결되었습니다",
"connect-fail": "연결 실패",
"preset": "프리셋",
"openmcp-document": "OpenMCP 공식 문서",
"star-our-project": "우리 프로젝트 스타",
"document": "공식 문서",
"join-discussion": "토론 그룹에 참여",
"comment-for-us": "우리를 위해 리뷰를 작성해 주세요!",
"openmcp-developed-by": "OpenMCP Client {version}은 {author}에 의해 개발되었습니다"
} }

View File

@ -172,5 +172,17 @@
"read-document": "Читать документацию", "read-document": "Читать документацию",
"report-issue": "Сообщить о проблеме", "report-issue": "Сообщить о проблеме",
"join-project": "Участвовать в проекте", "join-project": "Участвовать в проекте",
"comment-plugin": "Плагин комментариев" "comment-plugin": "Плагин комментариев",
"preset-env-sync.success": "Предустановленные переменные среды синхронизированы",
"preset-env-sync.fail": "Не удалось синхронизировать предустановленные переменные среды",
"drag-to-fill-connect-parameters": "Перетащите, чтобы заполнить параметры подключения",
"connect-success": "Успешное подключение",
"connect-fail": "Ошибка подключения",
"preset": "Предустановка",
"openmcp-document": "Официальная документация OpenMCP",
"star-our-project": "Звезда нашего проекта",
"document": "Официальная документация",
"join-discussion": "Присоединиться к дискуссионной группе",
"comment-for-us": "Напишите отзыв для нас!",
"openmcp-developed-by": "OpenMCP Client {version} разработан {author}"
} }

View File

@ -158,5 +158,17 @@
"waiting-mcp-server": "等待 MCP 服务器响应", "waiting-mcp-server": "等待 MCP 服务器响应",
"parallel-tool-calls": "允许模型在单轮回复中调用多个工具", "parallel-tool-calls": "允许模型在单轮回复中调用多个工具",
"proxy-server": "代理服务器", "proxy-server": "代理服务器",
"update-model-list": "更新模型列表" "update-model-list": "更新模型列表",
"preset-env-sync.success": "预设环境变量同步完成",
"preset-env-sync.fail": "预设环境变量同步失败",
"drag-to-fill-connect-parameters": "拖拽以填充连接参数",
"connect-success": "连接成功",
"connect-fail": "连接失败",
"preset": "预设",
"openmcp-document": "OpenMCP 官方文档",
"star-our-project": "Star 我们的项目",
"document": "官方文档",
"join-discussion": "加入讨论群",
"comment-for-us": "为我们撰写评价!",
"openmcp-developed-by": "OpenMCP Client {version} 由 {author} 开发"
} }

View File

@ -172,5 +172,17 @@
"read-document": "閱讀文件", "read-document": "閱讀文件",
"report-issue": "報告問題", "report-issue": "報告問題",
"join-project": "參與專案", "join-project": "參與專案",
"comment-plugin": "評論插件" "comment-plugin": "評論插件",
"preset-env-sync.success": "預設環境變數同步完成",
"preset-env-sync.fail": "預設環境變數同步失敗",
"drag-to-fill-connect-parameters": "拖曳以填充連接參數",
"connect-success": "連接成功",
"connect-fail": "連接失敗",
"preset": "預設",
"openmcp-document": "OpenMCP 官方文件",
"star-our-project": "給我們的項目加星",
"document": "官方文件",
"join-discussion": "加入討論群",
"comment-for-us": "為我們撰寫評價!",
"openmcp-developed-by": "OpenMCP Client {version} 由 {author} 開發"
} }

View File

@ -1,36 +1,40 @@
<template> <template>
<div class="about-container" > <div class="about-container">
<span class="about-icon-container"> <span class="about-icon-container">
<div class="openmcp-image"></div> <div class="openmcp-image"></div>
<span>openmcp</span> <span>OpenMCP</span>
</span> </span>
<p> <p>
OpenMCP Client 0.1.5 OpenMCP@<a href="https://www.zhihu.com/people/can-meng-zhong-de-che-xian">锦恢</a> 开发 {{ t('openmcp-developed-by', { version, author }) }}
</p> </p>
<p>
软件已开源 <a href="https://github.com/LSTM-Kirigaya/openmcp-client" target="_blank"> <div style="display: inline-flex;">
LSTM-Kirigaya/openmcp-client <el-button class="join-qq" type="primary"
</a> @click="gotoWebsite('https://github.com/LSTM-Kirigaya/openmcp-client')">
<span class="iconfont icon-star"></span>
{{ t('star-our-project') }}
</el-button>
<el-button class="join-qq" type="primary" @click="gotoWebsite('https://kirigaya.cn/openmcp')">
<span class="iconfont icon-wendang"></span>
{{ t('document') }}
</el-button>
</div>
<br> <br>
请遵循开源协议进行分发和二次开发
</p>
<p>
如果感兴趣欢迎加入我们的QQ群和我们讨论
</p>
<div style="display: inline-flex;"> <div style="display: inline-flex;">
<el-button class="join-qq" type="primary" <el-button class="join-qq" type="primary"
@click="joinQQGroup('https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD')"> @click="joinQQGroup('https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD')">
<span class="iconfont icon-QQ"></span> <span class="iconfont icon-QQ"></span>
加入 OpenMCP 技术群 {{ t('join-discussion') }}
</el-button> </el-button>
<el-button type="success" class="join-qq" <el-button type="success" class="join-qq"
@click="gotoWebsite('https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp&ssr=false#review-details')"> @click="gotoWebsite('https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp&ssr=false#review-details')">
<span class="iconfont icon-star"></span> <span class="iconfont icon-star"></span>
OpenMCP 撰写评价 {{ t('comment-for-us') }}
</el-button> </el-button>
</div> </div>
@ -39,6 +43,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const version = '0.1.5';
const author = 'LSTM-Kirigaya (锦恢)';
defineComponent({ name: 'about' }); defineComponent({ name: 'about' });
@ -66,7 +76,6 @@ function gotoWebsite(url: string) {
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3);
border-radius: .8em; border-radius: .8em;
padding: 20px 30px; padding: 20px 30px;
color: var(--main-color);
background-color: var(--background); background-color: var(--background);
display: flex; display: flex;
font-size: 30px; font-size: 30px;
@ -74,6 +83,14 @@ function gotoWebsite(url: string) {
margin-bottom: 20px; margin-bottom: 20px;
} }
.about-icon-container span {
background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-weight: bold;
font-size: 45px;
}
.about-icon-container .iconfont { .about-icon-container .iconfont {
font-size: 180px; font-size: 180px;

View File

@ -7,8 +7,8 @@
v-model="envEnabled" v-model="envEnabled"
@change="(enable: boolean) => client.handleEnvSwitch(enable)" @change="(enable: boolean) => client.handleEnvSwitch(enable)"
inline-prompt inline-prompt
active-text="预设" :active-text="t('preset')"
inactive-text="预设" :inactive-text="t('preset')"
></el-switch> ></el-switch>
</div> </div>
<div class="input-env"> <div class="input-env">

View File

@ -3,7 +3,7 @@
<div class="connection-container" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop"> <div class="connection-container" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop">
<div v-if="isDraging" class="drag-mask"> <div v-if="isDraging" class="drag-mask">
<span class="iconfont icon-connect"></span> <span class="iconfont icon-connect"></span>
<span>拖拽以填充连接参数</span> <span>{{ t('drag-to-fill-connect-parameters') }}</span>
</div> </div>
<div class="connect-panel-container left" :ref="el => client.connectionSettingRef = el"> <div class="connect-panel-container left" :ref="el => client.connectionSettingRef = el">
<ConnectionMethod :index="props.index" /> <ConnectionMethod :index="props.index" />

View File

@ -7,6 +7,9 @@ import { getPlatform } from "@/api/platform";
import type { PromptsGetResponse, PromptsListResponse, PromptTemplate, Resources, ResourcesListResponse, ResourcesReadResponse, ResourceTemplate, ResourceTemplatesListResponse, ToolCallResponse, ToolItem, ToolsListResponse } from "@/hook/type"; import type { PromptsGetResponse, PromptsListResponse, PromptTemplate, Resources, ResourcesListResponse, ResourcesReadResponse, ResourceTemplate, ResourceTemplatesListResponse, ToolCallResponse, ToolItem, ToolsListResponse } from "@/hook/type";
import { mcpSetting } from "@/hook/mcp"; import { mcpSetting } from "@/hook/mcp";
import chalk from "chalk"; import chalk from "chalk";
import I18n from '@/i18n';
const { t } = I18n.global;
export const connectionSelectDataViewOption: ConnectionTypeOptionItem[] = [ export const connectionSelectDataViewOption: ConnectionTypeOptionItem[] = [
{ {
@ -337,7 +340,7 @@ export class McpClient {
const message = msg.toString(); const message = msg.toString();
this.connectionResult.logString.push({ this.connectionResult.logString.push({
type: 'error', type: 'error',
title: '连接失败', title: t('connect-fail'),
message message
}); });
@ -346,7 +349,7 @@ export class McpClient {
} else { } else {
this.connectionResult.logString.push({ this.connectionResult.logString.push({
type: 'info', type: 'info',
title: msg.name + ' ' + msg.version + ' 连接成功', title: msg.name + ' ' + msg.version + ' ' + t('connect-success'),
message: JSON.stringify(msg, null, 2) message: JSON.stringify(msg, null, 2)
}); });
} }
@ -437,16 +440,17 @@ export class McpClient {
}); });
if (code === 200) { if (code === 200) {
this.connectionResult.logString.push({ this.connectionResult.logString.push({
type: 'info', type: 'info',
title: '预设环境变量同步完成' title: t('preset-env-sync.success')
}); });
return msg; return msg;
} else { } else {
this.connectionResult.logString.push({ this.connectionResult.logString.push({
type: 'error', type: 'error',
title: '预设环境变量同步失败', title: t('preset-env-sync.fail'),
message: msg.toString() message: msg.toString()
}); });
} }