Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/app/dto/request/mcp_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type McpServerCreate struct {
HostIP string `json:"hostIP"`
StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport" validate:"required"`
Type string `json:"type" validate:"required"`
}

type McpServerUpdate struct {
Expand Down
1 change: 1 addition & 0 deletions agent/app/model/mcp_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ type McpServer struct {
HostIP string `json:"hostIP"`
StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport"`
Type string `json:"type"`
}
39 changes: 27 additions & 12 deletions agent/app/service/mcp_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ func (m McpServerService) Page(req request.McpServerSearch) response.McpServersR
Environments: make([]request.Environment, 0),
Volumes: make([]request.Volume, 0),
}
project, _ := docker.GetComposeProject(item.Name, path.Join(global.Dir.McpDir, item.Name), []byte(item.DockerCompose), []byte(item.Env), true)
project, err := docker.GetComposeProject(item.Name, path.Join(global.Dir.McpDir, item.Name), []byte(item.DockerCompose), []byte(item.Env), true)
if err != nil {
global.LOG.Errorf("get mcp compose project error: %s", err.Error())
continue
}
for _, service := range project.Services {
if service.Environment != nil {
for key, value := range service.Environment {
Expand All @@ -86,11 +90,7 @@ func (m McpServerService) Page(req request.McpServerSearch) response.McpServersR
}

func (m McpServerService) Update(req request.McpServerUpdate) error {
go func() {
if err := docker.PullImage("supercorp/supergateway:latest"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
}()
go pullImage(req.Type)
mcpServer, err := mcpServerRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
Expand All @@ -115,6 +115,7 @@ func (m McpServerService) Update(req request.McpServerUpdate) error {
mcpServer.HostIP = req.HostIP
mcpServer.StreamableHttpPath = req.StreamableHttpPath
mcpServer.OutputTransport = req.OutputTransport
mcpServer.Type = req.Type
if err := handleCreateParams(mcpServer, req.Environments, req.Volumes); err != nil {
return err
}
Expand All @@ -137,11 +138,7 @@ func (m McpServerService) Update(req request.McpServerUpdate) error {
}

func (m McpServerService) Create(create request.McpServerCreate) error {
go func() {
if err := docker.PullImage("supercorp/supergateway:latest"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
}()
go pullImage(create.Type)
servers, _ := mcpServerRepo.List()
for _, server := range servers {
if server.Port == create.Port {
Expand Down Expand Up @@ -177,6 +174,7 @@ func (m McpServerService) Create(create request.McpServerCreate) error {
HostIP: create.HostIP,
StreamableHttpPath: create.StreamableHttpPath,
OutputTransport: create.OutputTransport,
Type: create.Type,
}
if err := handleCreateParams(mcpServer, create.Environments, create.Volumes); err != nil {
return err
Expand Down Expand Up @@ -590,6 +588,11 @@ func handleCreateParams(mcpServer *model.McpServer, environments []request.Envir
}
serviceValue["volumes"] = volumeList
}
if mcpServer.Type == "npx" {
serviceValue["image"] = "supercorp/supergateway:latest"
} else {
serviceValue["image"] = "supercorp/supergateway:uvx"
}

services[mcpServer.Name] = serviceValue
composeByte, err := yaml.Marshal(composeMap)
Expand Down Expand Up @@ -641,7 +644,7 @@ func syncMcpServerContainerStatus(mcpServer *model.McpServer) error {
case "restarting":
mcpServer.Status = constant.StatusRestarting
default:
if mcpServer.Status != constant.StatusBuilding {
if mcpServer.Status != constant.StatusStarting {
mcpServer.Status = constant.StatusStopped
}
}
Expand All @@ -656,3 +659,15 @@ func GetWebsiteID() uint {
websiteIDUint, _ := strconv.ParseUint(websiteID.Value, 10, 64)
return uint(websiteIDUint)
}

func pullImage(imageType string) {
if imageType == "npx" {
if err := docker.PullImage("supercorp/supergateway:latest"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
} else {
if err := docker.PullImage("supercorp/supergateway:uvx"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
}
}
1 change: 1 addition & 0 deletions agent/init/migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func InitAgentDB() {
migrations.AddColumnToAlert,
migrations.UpdateWebsiteSSL,
migrations.AddQuickJump,
migrations.UpdateMcpServerAddType,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)
Expand Down
13 changes: 13 additions & 0 deletions agent/init/migration/migrations/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,3 +496,16 @@ var AddQuickJump = &gormigrate.Migration{
return nil
},
}

var UpdateMcpServerAddType = &gormigrate.Migration{
ID: "20250904-update-mcp-server",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.McpServer{}); err != nil {
return err
}
if err := tx.Model(&model.McpServer{}).Where("1=1").Update("type", "npx").Error; err != nil {
return err
}
return nil
},
}
1 change: 1 addition & 0 deletions frontend/src/api/interface/ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export namespace AI {
url: string;
outputTransport: string;
streamableHttpPath: string;
type: string;
}

export interface McpServerSearch extends ReqPage {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,6 @@ const message = {
server: 'MCP Server',
create: 'Add MCP Server',
edit: 'Edit MCP Server',
commandHelper: 'For example: npx -y {0}',
baseUrl: 'External Access Path',
baseUrlHelper: 'For example: http://192.168.1.2:8000',
ssePath: 'SSE Path',
Expand All @@ -717,6 +716,8 @@ const message = {
outputTransport: 'Output Type',
streamableHttpPath: 'Streaming Path',
streamableHttpPathHelper: 'For example: /mcp, note that it should not overlap with other Servers',
npxHelper: 'Suitable for mcp started with npx or binary',
uvxHelper: 'Suitable for mcp started with uvx',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,6 @@ const message = {
server: 'MCP サーバー',
create: 'サーバーを追加',
edit: 'サーバーを編集',
commandHelper: '例: npx -y {0}',
baseUrl: '外部アクセスパス',
baseUrlHelper: '例: http://192.168.1.2:8000',
ssePath: 'SSE パス',
Expand All @@ -705,6 +704,8 @@ const message = {
outputTransport: '出力タイプ',
streamableHttpPath: 'ストリーミングパス',
streamableHttpPathHelper: '例:/mcp、他のサーバーと重複しないように注意してください',
npxHelper: 'npx またはバイナリで起動する mcp に適しています',
uvxHelper: 'uvx で起動する mcp に適しています',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,6 @@ const message = {
server: 'MCP サーバー',
create: 'サーバーを追加',
edit: 'サーバーを編集',
commandHelper: '例: npx -y {0}',
baseUrl: '外部アクセスパス',
baseUrlHelper: '例: http://192.168.1.2:8000',
ssePath: 'SSE パス',
Expand All @@ -701,6 +700,8 @@ const message = {
outputTransport: '출력 유형',
streamableHttpPath: '스트리밍 경로',
streamableHttpPathHelper: '예: /mcp, 다른 서버와 중복되지 않도록 주의하세요',
npxHelper: 'npx 또는 바이너리로 시작하는 mcp에 적합',
uvxHelper: 'uvx로 시작하는 mcp에 적합',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/ms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ const message = {
server: 'Pelayan MCP',
create: 'Tambah Pelayan',
edit: 'Edit Pelayan',
commandHelper: 'Contoh: npx -y {0}',
baseUrl: 'Laluan Akses Luar',
baseUrlHelper: 'Contoh: http://192.168.1.2:8000',
ssePath: 'Laluan SSE',
Expand All @@ -718,6 +717,8 @@ const message = {
outputTransport: 'Jenis Output',
streamableHttpPath: 'Laluan Streaming',
streamableHttpPathHelper: 'Contoh: /mcp, elakkan daripada bertindan dengan pelayan lain',
npxHelper: 'Sesuai untuk mcp yang dimulakan dengan npx atau binari',
uvxHelper: 'Sesuai untuk mcp yang dimulakan dengan uvx',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/pt-br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,6 @@ const message = {
server: 'Servidor MCP',
create: 'Adicionar Servidor',
edit: 'Editar Servidor',
commandHelper: 'Por exemplo: npx -y {0}',
baseUrl: 'Caminho de Acesso Externo',
baseUrlHelper: 'Por exemplo: http://192.168.1.2:8000',
ssePath: 'Caminho SSE',
Expand All @@ -714,6 +713,8 @@ const message = {
outputTransport: 'Tipo de Saída',
streamableHttpPath: 'Caminho de Streaming',
streamableHttpPathHelper: 'Por exemplo: /mcp, certifique-se de que não se sobreponha a outros Servidores',
npxHelper: 'Adequado para mcp iniciado com npx ou binário',
uvxHelper: 'Adequado para mcp iniciado com uvx',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,6 @@ const message = {
server: 'Сервер MCP',
create: 'Добавить сервер',
edit: 'Редактировать сервер',
commandHelper: 'Например: npx -y {0}',
baseUrl: 'Внешний путь доступа',
baseUrlHelper: 'Например: http://192.168.1.2:8000',
ssePath: 'Путь SSE',
Expand All @@ -711,6 +710,8 @@ const message = {
outputTransport: 'Тип вывода',
streamableHttpPath: 'Путь потоковой передачи',
streamableHttpPathHelper: 'Например: /mcp, обратите внимание, чтобы не перекрывать другие серверы',
npxHelper: 'Подходит для mcp, запущенного с помощью npx или бинарного файла',
uvxHelper: 'Подходит для mcp, запущенного с помощью uvx',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,6 @@ const message = {
server: 'MCP Sunucusu',
create: 'MCP Sunucusu Ekle',
edit: 'MCP Sunucusunu Düzenle',
commandHelper: 'Örneğin: npx -y {0}',
baseUrl: 'Harici Erişim Yolu',
baseUrlHelper: 'Örneğin: http://192.168.1.2:8000',
ssePath: 'SSE Yolu',
Expand All @@ -727,6 +726,8 @@ const message = {
outputTransport: 'Çıktı Türü',
streamableHttpPath: 'Akış Yolu',
streamableHttpPathHelper: 'Örneğin: /mcp, diğer Sunucularla çakışmaması gerektiğine dikkat edin',
npxHelper: 'npx veya ikili dosya ile başlatılan mcp için uygundur',
uvxHelper: 'uvx ile başlatılan mcp için uygundur',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/zh-Hant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,6 @@ const message = {
server: 'MCP Server',
create: '创建 MCP Server',
edit: '編輯 MCP Server',
commandHelper: '例如:npx -y {0}',
baseUrl: '外部訪問路徑',
baseUrlHelper: '例如:http://192.168.1.2:8000',
ssePath: 'SSE 路徑',
Expand All @@ -691,6 +690,8 @@ const message = {
outputTransport: '輸出類型',
streamableHttpPath: '流式傳輸路徑',
streamableHttpPathHelper: '例如:/mcp, 注意不要與其他 Server 重複',
npxHelper: '適合 npx 或者 二進制啟動的 mcp',
uvxHelper: '適合 uvx 啟動的 mcp',
},
},
container: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,6 @@ const message = {
server: 'MCP Server',
create: '创建 MCP Server',
edit: '编辑 MCP Server',
commandHelper: '例如:npx -y {0}',
baseUrl: '外部访问路径',
baseUrlHelper: '例如:http://192.168.1.1:8000',
ssePath: 'SSE 路径',
Expand All @@ -690,6 +689,8 @@ const message = {
outputTransport: '输出类型',
streamableHttpPath: '流式传输路径',
streamableHttpPathHelper: '例如:/mcp, 注意不要与其他 Server 重复',
npxHelper: '适合 npx 或者 二进制启动的 mcp',
uvxHelper: '适合 uvx 启动的 mcp',
},
},
container: {
Expand Down
22 changes: 18 additions & 4 deletions frontend/src/views/ai/mcp/server/operate/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,27 @@
<el-form-item :label="$t('commons.table.name')" prop="name">
<el-input v-model="mcpServer.name" :disabled="mode == 'edit'" />
</el-form-item>
<el-form-item :label="$t('commons.table.type')" prop="type">
<el-select v-model="mcpServer.type">
<el-option label="npx" value="npx" />
<el-option label="uvx" value="uvx" />
</el-select>
<span class="input-help">
{{ $t('aiTools.mcp.' + mcpServer.type + 'Helper') }}
</span>
</el-form-item>
<el-form-item :label="$t('runtime.runScript')" prop="command">
<el-input
v-model="mcpServer.command"
type="textarea"
:rows="3"
:placeholder="$t('aiTools.mcp.commandPlaceHolder')"
:placeholder="
$t('ssl.commonNameHelper') +
(mcpServer.type == 'npx'
? ' npx -y @modelcontextprotocol/server-github'
: ' uvx mcp-server-fetch')
"
></el-input>
<span class="input-help">
{{ $t('aiTools.mcp.commandHelper', ['@modelcontextprotocol/server-github']) }}
</span>
</el-form-item>
<div>
<el-text>{{ $t('aiTools.mcp.environment') }}</el-text>
Expand Down Expand Up @@ -160,6 +171,7 @@ const newMcpServer = () => {
url: '',
outputTransport: 'sse',
streamableHttpPath: '',
type: 'npx',
};
};
const em = defineEmits(['close']);
Expand All @@ -175,6 +187,7 @@ const rules = ref({
value: [Rules.requiredInput],
outputTransport: [Rules.requiredSelect],
streamableHttpPath: [Rules.requiredInput],
type: [Rules.requiredSelect],
});
const hasWebsite = ref(false);

Expand All @@ -201,6 +214,7 @@ const acceptParams = async (params: AI.McpServer) => {
mcpServer.value.protocol = parts[0];
mcpServer.value.url = parts[1];
mcpServer.value.outputTransport = mcpServer.value.outputTransport || 'sse';
mcpServer.value.type = mcpServer.value.type || 'npx';
} else {
mcpServer.value = newMcpServer();
if (params.port) {
Expand Down
Loading