feat: 添加MCP服务器状态切换功能

This commit is contained in:
kuaifan 2025-10-25 16:39:50 +08:00
parent 00b4d6a748
commit 8958f2f234
7 changed files with 259 additions and 9 deletions

17
electron/electron.js vendored
View File

@ -46,7 +46,7 @@ const utils = require('./lib/utils');
const config = require('./package.json');
const electronDown = require("./electron-down");
const electronMenu = require("./electron-menu");
const { startMCPServer } = require("./lib/mcp");
const { startMCPServer, stopMCPServer } = require("./lib/mcp");
// 实例初始化
const userConf = new electronConf()
@ -1159,8 +1159,6 @@ if (!getTheLock) {
preCreateChildWindow()
// 监听主题变化
monitorThemeChanges()
// 启动 MCP 服务器
startMCPServer(mainWindow, mcpPort)
// 创建托盘
if (['darwin', 'win32'].includes(process.platform) && utils.isJson(config.trayIcon)) {
mainTray = new Tray(path.join(__dirname, config.trayIcon[isDevelopMode ? 'dev' : 'prod'][process.platform === 'darwin' ? 'mac' : 'win']));
@ -1664,6 +1662,19 @@ ipcMain.on('setDockBadge', (event, args) => {
event.returnValue = "ok"
})
/**
* MCP 服务器状态切换
* @param args
*/
ipcMain.on('mcpServerToggle', (event, args) => {
const { running } = args;
if (running === 'running') {
startMCPServer(mainWindow, mcpPort)
} else {
stopMCPServer()
}
})
/**
* 复制Base64图片
* @param args

View File

@ -28,7 +28,9 @@
placement="right-start">
<DropdownItem :divided="!!item.divided">
<div class="manage-menu-flex">
{{$L(item.name)}}
<div class="manage-menu-title">
{{$L(item.name)}}
</div>
<Icon type="ios-arrow-forward"></Icon>
</div>
</DropdownItem>
@ -66,7 +68,9 @@
placement="right-start">
<DropdownItem :divided="!!item.divided">
<div class="manage-menu-flex">
{{$L(item.name)}}
<div class="manage-menu-title">
{{$L(item.name)}}
</div>
<Icon type="ios-arrow-forward"></Icon>
</div>
</DropdownItem>
@ -86,7 +90,12 @@
:name="item.path"
:style="item.style || {}">
<div class="manage-menu-flex">
{{$L(item.name)}}
<div class="manage-menu-title">
{{$L(item.name)}}
</div>
<Icon
v-if="item.selected === true"
type="md-checkmark" />
<Badge
v-if="item.path === 'version'"
class="manage-menu-report-badge"
@ -317,6 +326,9 @@
</div>
</Modal>
<!--弹出 MCP 服务器信息-->
<MCPHelper v-model="mcpHelperShow"/>
<!--导出任务统计-->
<TaskExport v-model="exportTaskShow"/>
@ -415,6 +427,7 @@
import { mapState, mapGetters } from 'vuex'
import ProjectArchived from "./manage/components/ProjectArchived";
import TeamManagement from "./manage/components/TeamManagement";
import MCPHelper from "./manage/components/MCPHelper";
import FavoriteManagement from "./manage/components/FavoriteManagement";
import RecentManagement from "./manage/components/RecentManagement";
import ProjectManagement from "./manage/components/ProjectManagement";
@ -460,6 +473,7 @@ export default {
DrawerOverlay,
ProjectManagement,
TeamManagement,
MCPHelper,
FavoriteManagement,
RecentManagement,
ProjectArchived,
@ -529,9 +543,11 @@ export default {
approveShow: false,
approveDetails: {id: 0},
approveDetailsShow: false,
taskBrowseLoading: false,
taskBrowseHistory: [], //
taskBrowseHistory: [],
mcpHelperShow: false,
}
},
@ -596,6 +612,8 @@ export default {
'formOptions',
'mobileTabbar',
'longpressData',
'mcpServerStatus'
]),
...mapGetters(['dashboardTask', "filterMicroAppsMenusMain"]),
@ -699,6 +717,7 @@ export default {
{path: 'taskBrowse', name: '最近打开的任务'},
{path: 'favorite', name: '我的收藏'},
{path: 'download', name: '下载内容', visible: !!this.$Electron},
{path: 'mcpServer', name: '启用桌面 MCP 服务器', visible: !!this.$Electron, selected: this.mcpServerStatus.running === 'running'},
];
if (userIsAdmin) {
array.push(...[
@ -848,6 +867,16 @@ export default {
},
immediate: true
},
mcpServerStatus: {
handler(data) {
if (!this.$Electron) {
return;
}
this.$Electron.sendMessage('mcpServerToggle', data);
},
immediate: true
}
},
methods: {
@ -923,6 +952,12 @@ export default {
theme: this.themeName,
});
return;
case 'mcpServer':
if (this.mcpServerStatus.running !== 'running') {
this.mcpHelperShow = true;
}
this.$store.dispatch('toggleMcpServer');
return;
case 'logout':
$A.modalConfirm({
title: '退出登录',
@ -1549,7 +1584,7 @@ export default {
*/
loadTaskBrowseHistory() {
if (this.taskBrowseLoading) return
this.taskBrowseLoading = true
this.$store.dispatch("getTaskBrowseHistory", 20).then(({data}) => {
//

View File

@ -0,0 +1,167 @@
<template>
<Modal v-model="mcpHelperShow" :title="$L('桌面 MCP 服务器')" :mask-closable="false" width="700">
<div class="mcp-helper-content">
<Alert type="success" show-icon>
{{ $L('MCP 服务器已启动成功!') }}
<span slot="desc">
{{ $L('服务地址') }}: <code>http://localhost:22224/sse</code>
</span>
</Alert>
<div class="mcp-section">
<h3>🔗 {{ $L('接入配置') }}</h3>
<p>{{ $L('以接入 Claude 为例,在配置文件中添加以下配置') }}:</p>
<div class="mcp-code-block">
<pre ref="mcpConfig">{{ mcpConfig }}</pre>
<Button size="small" class="mcp-copy-btn" @click="copyMcpConfig">{{ $L('复制配置') }}</Button>
</div>
</div>
<div class="mcp-section">
<h3>💡 {{ $L('使用示例') }}</h3>
<p>{{ $L('配置生效后,即可通过自然语言使用 MCP 服务') }}:</p>
<ul class="mcp-examples">
<li>"{{ $L("查看我未完成的任务") }}"</li>
<li>"{{ $L("搜索包含'报告'的任务") }}"</li>
<li>"{{ $L("标记任务456为已完成") }}"</li>
<li>"{{ $L("在项目1中创建任务完成用户手册") }}"</li>
<li>"{{ $L("把任务789的截止时间改为下周五") }}"</li>
<li>"{{ $L("我有哪些项目") }}"</li>
</ul>
</div>
</div>
<div slot="footer" class="adaption">
<Button type="primary" @click="mcpHelperShow = false">{{ $L('我知道了') }}</Button>
</div>
</Modal>
</template>
<style lang="scss" scoped>
.mcp-helper-content {
.mcp-section {
margin-top: 20px;
h3 {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
color: #333;
}
p {
margin-bottom: 10px;
color: #666;
line-height: 1.6;
}
.mcp-code-block {
position: relative;
background: #f5f7fa;
border: 1px solid #e4e7ed;
border-radius: 4px;
padding: 12px;
margin: 12px 0;
pre {
margin: 0;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 13px;
line-height: 1.6;
color: #333;
overflow-x: auto;
}
.mcp-copy-btn {
position: absolute;
top: 8px;
right: 8px;
}
}
.mcp-hint {
font-size: 13px;
color: #999;
margin-top: 8px;
display: flex;
align-items: center;
gap: 4px;
code {
background: #f5f7fa;
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
}
}
.mcp-examples {
margin: 12px 0;
padding-left: 20px;
li {
margin: 8px 0;
color: #666;
line-height: 1.6;
font-size: 14px;
&:before {
content: '•';
color: #2d8cf0;
font-weight: bold;
display: inline-block;
width: 1em;
margin-left: -1em;
}
}
}
}
code {
background: #f5f7fa;
padding: 2px 6px;
border-radius: 3px;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 13px;
color: #e96900;
}
}
</style>
<script>
export default {
name: "MCPHelper",
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return {
mcpConfig: `{
"mcpServers": {
"DooTask": {
"url": "http://localhost:22224/sse"
}
}
}`
}
},
computed: {
mcpHelperShow: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value);
}
}
},
methods: {
copyMcpConfig() {
this.copyText(this.$refs.mcpConfig.textContent);
}
}
}
</script>

View File

@ -1081,6 +1081,7 @@ export default {
cacheTranslations: await $A.IDBArray("cacheTranslations"),
cacheEmojis: await $A.IDBArray("cacheEmojis"),
userInfo: await $A.IDBJson("userInfo"),
mcpServerStatus: await $A.IDBJson("mcpServerStatus"),
cacheVersion: state.cacheVersion,
};
await $A.IDBClear();
@ -1141,6 +1142,7 @@ export default {
'userInfo',
'taskRelatedCache',
'dialogCommonCountCache',
'mcpServerStatus'
]
};
@ -5044,4 +5046,24 @@ export default {
commit("microApps/data", data|| [])
}
},
/** *****************************************************************************************/
/** *********************************** MCP Server ******************************************/
/** *****************************************************************************************/
/**
* 切换 MCP 服务器状态
* @param state
* @param commit
*/
async toggleMcpServer({state, commit}) {
if (state.mcpServerStatus.running === 'running') {
// 停止 MCP 服务器
commit('mcp/server/status', {running: 'stopped'});
} else {
// 启动 MCP 服务器
commit('mcp/server/status', {running: 'running'});
}
}
}

View File

@ -439,4 +439,9 @@ export default {
$A.IDBSave("microAppsIds", state.microAppsIds = data.map(item => item.id));
$A.IDBSave("microAppsMenus", state.microAppsMenus = menus);
},
// MCP 服务器状态
'mcp/server/status': function(state, data) {
$A.IDBSave("mcpServerStatus", state.mcpServerStatus = data);
},
}

View File

@ -277,4 +277,7 @@ export default {
microAppsInstalled: [],
microAppsIds: [],
microAppsMenus: [],
// MCP 服务器状态
mcpServerStatus: {running: 'stopped'},
};

View File

@ -418,6 +418,13 @@
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 8px;
.manage-menu-title {
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ivu-icon {
color: $primary-text-color;
}