mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-02-04 14:33:01 +08:00
feat: add config for mcp server (#8331)
This commit is contained in:
@@ -118,8 +118,12 @@ func (m McpServerService) Update(req request.McpServerUpdate) error {
|
||||
if err := files.NewFileOp().SaveFile(dockerComposePath, mcpServer.DockerCompose, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
startMcp(mcpServer)
|
||||
return syncMcpServerContainerStatus(mcpServer)
|
||||
mcpServer.Status = constant.RuntimeStarting
|
||||
if err := mcpServerRepo.Save(mcpServer); err != nil {
|
||||
return err
|
||||
}
|
||||
go startMcp(mcpServer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m McpServerService) Create(create request.McpServerCreate) error {
|
||||
@@ -150,7 +154,7 @@ func (m McpServerService) Create(create request.McpServerCreate) error {
|
||||
ContainerName: create.ContainerName,
|
||||
Port: create.Port,
|
||||
Command: create.Command,
|
||||
Status: constant.RuntimeNormal,
|
||||
Status: constant.RuntimeStarting,
|
||||
BaseURL: create.BaseURL,
|
||||
SsePath: create.SsePath,
|
||||
Dir: mcpDir,
|
||||
@@ -175,9 +179,9 @@ func (m McpServerService) Create(create request.McpServerCreate) error {
|
||||
if err := mcpServerRepo.Create(mcpServer); err != nil {
|
||||
return err
|
||||
}
|
||||
startMcp(mcpServer)
|
||||
addProxy(mcpServer)
|
||||
return syncMcpServerContainerStatus(mcpServer)
|
||||
go startMcp(mcpServer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m McpServerService) Delete(id uint) error {
|
||||
@@ -584,6 +588,7 @@ func startMcp(mcpServer *model.McpServer) {
|
||||
mcpServer.Status = constant.RuntimeRunning
|
||||
mcpServer.Message = ""
|
||||
}
|
||||
_ = syncMcpServerContainerStatus(mcpServer)
|
||||
}
|
||||
|
||||
func syncMcpServerContainerStatus(mcpServer *model.McpServer) error {
|
||||
|
||||
@@ -35,6 +35,7 @@ var WebUrlMap = map[string]struct{}{
|
||||
"/ai": {},
|
||||
"/ai/model": {},
|
||||
"/ai/gpu": {},
|
||||
"/ai/mcp": {},
|
||||
|
||||
"/containers": {},
|
||||
"/containers/container": {},
|
||||
|
||||
@@ -2543,8 +2543,8 @@ const message = {
|
||||
env: 'Environments',
|
||||
noenv: 'None',
|
||||
net: 'Network connections',
|
||||
laddr: 'Source address/port',
|
||||
raddr: 'Destination address/port',
|
||||
laddr: 'Local address/port',
|
||||
raddr: 'Remote address/port',
|
||||
stopProcess: 'End',
|
||||
viewDetails: 'Details',
|
||||
stopProcessWarn: 'Are you sure you want to end this process (PID:{0})?',
|
||||
|
||||
@@ -2380,8 +2380,8 @@ const message = {
|
||||
env: '環境變數',
|
||||
noenv: '無',
|
||||
net: '網路連線',
|
||||
laddr: '源地址/埠',
|
||||
raddr: '目標地址/埠',
|
||||
laddr: '本地地址/埠',
|
||||
raddr: '远程地址/埠',
|
||||
stopProcess: '結束',
|
||||
viewDetails: '查看詳情',
|
||||
stopProcessWarn: '是否確定結束此行程 (PID:{0})?',
|
||||
|
||||
@@ -2382,8 +2382,8 @@ const message = {
|
||||
env: '环境变量',
|
||||
noenv: '无',
|
||||
net: '网络连接',
|
||||
laddr: '源地址/端口',
|
||||
raddr: '目标地址/端口',
|
||||
laddr: '本地地址/端口',
|
||||
raddr: '远程地址/端口',
|
||||
stopProcess: '结束',
|
||||
viewDetails: '查看详情',
|
||||
stopProcessWarn: '是否确定结束此进程 (PID:{0})?',
|
||||
|
||||
51
frontend/src/views/ai/mcp/server/config/index.vue
Normal file
51
frontend/src/views/ai/mcp/server/config/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
v-model="open"
|
||||
size="50%"
|
||||
>
|
||||
<template #header>
|
||||
<DrawerHeader :header="$t('menu.config')" :back="handleClose" />
|
||||
</template>
|
||||
<el-input type="textarea" :autosize="{ minRows: 10, maxRows: 20 }" v-model="prettyJson" readonly />
|
||||
<CopyButton :content="prettyJson" class="mt-2" />
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { AI } from '@/api/interface/ai';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const open = ref(false);
|
||||
const jsonObj = ref({
|
||||
mcpServers: {},
|
||||
});
|
||||
const prettyJson = ref('');
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
const acceptParams = (mcpServer: AI.McpServer) => {
|
||||
jsonObj.value.mcpServers = {};
|
||||
jsonObj.value.mcpServers[mcpServer.name] = {
|
||||
url: mcpServer.baseUrl + mcpServer.ssePath,
|
||||
};
|
||||
if (mcpServer.environments) {
|
||||
jsonObj.value.mcpServers[mcpServer.name].env = {};
|
||||
for (const env of mcpServer.environments) {
|
||||
jsonObj.value.mcpServers[mcpServer.name].env[env.key] = env.value;
|
||||
}
|
||||
}
|
||||
prettyJson.value = JSON.stringify(jsonObj.value, null, 4);
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
@@ -18,7 +18,7 @@
|
||||
:label="$t('commons.table.name')"
|
||||
fix
|
||||
prop="name"
|
||||
min-width="120px"
|
||||
width="200px"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
@@ -27,18 +27,13 @@
|
||||
</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.table.port')" prop="port" max-width="50px">
|
||||
<template #default="{ row }">
|
||||
{{ row.port }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('mcp.externalUrl')" prop="baseUrl" min-width="200px">
|
||||
<template #default="{ row }">
|
||||
{{ row.baseUrl + row.ssePath }}
|
||||
<CopyButton :content="row.baseUrl + row.ssePath" type="icon" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.table.status')" prop="status" max-width="50px">
|
||||
<el-table-column :label="$t('commons.table.status')" prop="status" width="100px">
|
||||
<template #default="{ row }">
|
||||
<el-popover
|
||||
v-if="row.status === 'error'"
|
||||
@@ -57,7 +52,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.button.log')" prop="path" min-width="90px">
|
||||
<el-table-column :label="$t('commons.button.log')" prop="path" width="100px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
@click="openLog(row)"
|
||||
@@ -74,12 +69,12 @@
|
||||
:label="$t('commons.table.date')"
|
||||
:formatter="dateFormat"
|
||||
show-overflow-tooltip
|
||||
min-width="120"
|
||||
width="180"
|
||||
fix
|
||||
/>
|
||||
<fu-table-operations
|
||||
:ellipsis="mobile ? 0 : 10"
|
||||
:min-width="mobile ? 'auto' : 400"
|
||||
:min-width="mobile ? 'auto' : 300"
|
||||
:buttons="buttons"
|
||||
:label="$t('commons.table.operate')"
|
||||
fixed="right"
|
||||
@@ -92,6 +87,7 @@
|
||||
<OpDialog ref="opRef" @search="search" />
|
||||
<ComposeLogs ref="composeLogRef" />
|
||||
<BindDomain ref="bindDomainRef" @close="searchWithTimeOut" />
|
||||
<Config ref="configRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -107,6 +103,7 @@ import { GlobalStore } from '@/store';
|
||||
import i18n from '@/lang';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import BindDomain from './bind/index.vue';
|
||||
import Config from './config/index.vue';
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
const loading = ref(false);
|
||||
@@ -114,6 +111,7 @@ const createRef = ref();
|
||||
const opRef = ref();
|
||||
const composeLogRef = ref();
|
||||
const bindDomainRef = ref();
|
||||
const configRef = ref();
|
||||
const items = ref<AI.McpServer[]>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mcp-server-page-size',
|
||||
@@ -126,6 +124,12 @@ const mobile = computed(() => {
|
||||
});
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
label: i18n.global.t('menu.config'),
|
||||
click: (row: AI.McpServer) => {
|
||||
openConfig(row);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.edit'),
|
||||
click: (row: AI.McpServer) => {
|
||||
@@ -241,6 +245,10 @@ const openDomain = () => {
|
||||
bindDomainRef.value.acceptParams();
|
||||
};
|
||||
|
||||
const openConfig = (row: AI.McpServer) => {
|
||||
configRef.value.acceptParams(row);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
});
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<Volumes :volumes="mcpServer.volumes" />
|
||||
<Volumes :volumes="mcpServer.volumes" class="mb-2" />
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('commons.table.port')" prop="port">
|
||||
|
||||
Reference in New Issue
Block a user